📜  展平链表

📅  最后修改于: 2022-05-13 01:57:45.813000             🧑  作者: Mango

展平链表

给定一个链表,其中每个节点代表一个链表并包含两个其类型的指针:
(i) 指向主列表中下一个节点的指针(我们在下面的代码中称之为“右”指针)
(ii) 指向该节点所在的链表的指针(我们在下面的代码中将其称为“向下”指针)。
所有链表都已排序。看下面的例子

5 -> 10 -> 19 -> 28
       |    |     |     |
       V    V     V     V
       7    20    22    35
       |          |     |
       V          V     V
       8          50    40
       |                |
       V                V
       30               45

编写一个函数flatten() 将列表扁平化为单个链表。扁平化的链表也应该排序。例如,对于上面的输入列表,输出列表应该是 5->7->8->10->19->20->22->28->30->35->40->45->50 .

这个想法是对链表使用合并排序的 Merge() 过程。我们使用merge() 将列表一一合并。我们递归地将当前列表与已经展平的列表合并()。
向下指针用于链接扁平列表的节点。

下面是上述方法的实现:

C++
// C++ program for flattening a Linked List
#include 
using namespace std;
 
// Link list node
class Node
{
    public:
        int data;
        Node *right, *down;
};
 
Node* head = NULL;
 
// An utility function to merge two sorted
// linked lists
Node* merge(Node* a, Node* b)
{
     
    // If first linked list is empty then second
    // is the answer
    if (a == NULL)
        return b;
 
    // If second linked list is empty then first
    // is the result
    if (b == NULL)
        return a;
 
    // Compare the data members of the two linked
    // lists and put the larger one in the result
    Node* result;
 
    if (a->data < b->data)
    {
        result = a;
        result->down = merge(a->down, b);
    }
 
    else
    {
        result = b;
        result->down = merge(a, b->down);
    }
    result->right = NULL;
    return result;
}
 
Node* flatten(Node* root)
{
     
    // Base Cases
    if (root == NULL || root->right == NULL)
        return root;
 
    // Recur for list on right
    root->right = flatten(root->right);
 
    // Now merge
    root = merge(root, root->right);
 
    // Return the root
    // it will be in turn merged with its left
    return root;
}
 
// Utility function to insert a node at
// beginning of the linked list
Node* push(Node* head_ref, int data)
{
     
    // Allocate the Node & Put in the data
    Node* new_node = new Node();
 
    new_node->data = data;
    new_node->right = NULL;
 
    // Make next of new Node as head
    new_node->down = head_ref;
 
    // Move the head to point to new Node
    head_ref = new_node;
 
    return head_ref;
}
 
void printList()
{
    Node* temp = head;
    while (temp != NULL)
    {
        cout << temp->data << " ";
        temp = temp->down;
    }
    cout << endl;
}
 
// Driver code
int main()
{
     
    /* Let us create the following linked list
        5 -> 10 -> 19 -> 28
        |    |     |     |
        V    V     V     V
        7    20    22    35
        |          |     |
        V          V     V
        8          50    40
        |                |
        V                V
        30               45
    */
    head = push(head, 30);
    head = push(head, 8);
    head = push(head, 7);
    head = push(head, 5);
 
    head->right = push(head->right, 20);
    head->right = push(head->right, 10);
 
    head->right->right = push(head->right->right, 50);
    head->right->right = push(head->right->right, 22);
    head->right->right = push(head->right->right, 19);
 
    head->right->right->right = push(head->right->right->right, 45);
    head->right->right->right = push(head->right->right->right, 40);
    head->right->right->right = push(head->right->right->right, 35);
    head->right->right->right = push(head->right->right->right, 20);
 
    // Flatten the list
    head = flatten(head);
 
    printList();
    return 0;
}
 
// This code is contributed by rajsanghavi9.


Java
// Java program for flattening a Linked List
class LinkedList
{
    Node head;  // head of list
 
    /* Linked list Node*/
    class Node
    {
        int data;
        Node right, down;
        Node(int data)
        {
            this.data = data;
            right = null;
            down = null;
        }
    }
 
    // An utility function to merge two sorted linked lists
    Node merge(Node a, Node b)
    {
        // if first linked list is empty then second
        // is the answer
        if (a == null)     return b;
 
        // if second linked list is empty then first
        // is the result
        if (b == null)      return a;
 
        // compare the data members of the two linked lists
        // and put the larger one in the result
        Node result;
 
        if (a.data < b.data)
        {
            result = a;
            result.down =  merge(a.down, b);
        }
 
        else
        {
            result = b;
            result.down = merge(a, b.down);
        }
 
        result.right = null;
        return result;
    }
 
    Node flatten(Node root)
    {
        // Base Cases
        if (root == null || root.right == null)
            return root;
 
        // recur for list on right
        root.right = flatten(root.right);
 
        // now merge
        root = merge(root, root.right);
 
        // return the root
        // it will be in turn merged with its left
        return root;
    }
 
    /* Utility function to insert a node at beginning of the
       linked list */
    Node push(Node head_ref, int data)
    {
        /* 1 & 2: Allocate the Node &
                  Put in the data*/
        Node new_node = new Node(data);
 
        /* 3. Make next of new Node as head */
        new_node.down = head_ref;
 
        /* 4. Move the head to point to new Node */
        head_ref = new_node;
 
        /*5. return to link it back */
        return head_ref;
    }
 
    void printList()
    {
        Node temp = head;
        while (temp != null)
        {
            System.out.print(temp.data + " ");
            temp = temp.down;
        }
        System.out.println();
    }
 
    /* Driver program to test above functions */
    public static void main(String args[])
    {
        LinkedList L = new LinkedList();
 
        /* Let us create the following linked list
            5 -> 10 -> 19 -> 28
            |    |     |     |
            V    V     V     V
            7    20    22    35
            |          |     |
            V          V     V
            8          50    40
            |                |
            V                V
            30               45
        */
 
        L.head = L.push(L.head, 30);
        L.head = L.push(L.head, 8);
        L.head = L.push(L.head, 7);
        L.head = L.push(L.head, 5);
 
        L.head.right = L.push(L.head.right, 20);
        L.head.right = L.push(L.head.right, 10);
 
        L.head.right.right = L.push(L.head.right.right, 50);
        L.head.right.right = L.push(L.head.right.right, 22);
        L.head.right.right = L.push(L.head.right.right, 19);
 
        L.head.right.right.right = L.push(L.head.right.right.right, 45);
        L.head.right.right.right = L.push(L.head.right.right.right, 40);
        L.head.right.right.right = L.push(L.head.right.right.right, 35);
        L.head.right.right.right = L.push(L.head.right.right.right, 20);
 
        // flatten the list
        L.head = L.flatten(L.head);
 
        L.printList();
    }
} /* This code is contributed by Rajat Mishra */


Python3
# Python program for flattening a Linked List
 
class Node():
    def __init__(self,data):
        self.data = data
        self.right = None
        self.down = None
 
class LinkedList():
    def __init__(self):
 
        # head of list
        self.head = None
 
    # Utility function to insert a node at beginning of the
    #   linked list
    def push(self,head_ref,data):
 
        # 1 & 2: Allocate the Node &
        # Put in the data
        new_node = Node(data)
 
        # Make next of new Node as head
        new_node.down = head_ref
 
        # 4. Move the head to point to new Node
        head_ref = new_node
 
        # 5. return to link it back
        return head_ref
 
    def printList(self):
 
        temp = self.head
        while(temp != None):
            print(temp.data,end=" ")
            temp = temp.down
 
        print()
 
    # An utility function to merge two sorted linked lists
    def merge(self, a, b):
        # if first linked list is empty then second
        # is the answer
        if(a == None):
            return b
         
        # if second linked list is empty then first
        # is the result
        if(b == None):
            return a
 
        # compare the data members of the two linked lists
        # and put the larger one in the result
        result = None
 
        if (a.data < b.data):
            result = a
            result.down = self.merge(a.down,b)
        else:
            result = b
            result.down = self.merge(a,b.down)
 
        result.right = None
        return result
 
    def flatten(self, root):
 
        # Base Case
        if(root == None or root.right == None):
            return root
        # recur for list on right
 
        root.right = self.flatten(root.right)
 
        # now merge
        root = self.merge(root, root.right)
 
        # return the root
        # it will be in turn merged with its left
        return root
 
# Driver program to test above functions
L = LinkedList()
 
'''
Let us create the following linked list
            5 -> 10 -> 19 -> 28
            |    |     |     |
            V    V     V     V
            7    20    22    35
            |          |     |
            V          V     V
            8          50    40
            |                |
            V                V
            30               45
'''
L.head = L.push(L.head, 30);
L.head = L.push(L.head, 8);
L.head = L.push(L.head, 7);
L.head = L.push(L.head, 5);
 
L.head.right = L.push(L.head.right, 20);
L.head.right = L.push(L.head.right, 10);
 
L.head.right.right = L.push(L.head.right.right, 50);
L.head.right.right = L.push(L.head.right.right, 22);
L.head.right.right = L.push(L.head.right.right, 19);
 
L.head.right.right.right = L.push(L.head.right.right.right, 45);
L.head.right.right.right = L.push(L.head.right.right.right, 40);
L.head.right.right.right = L.push(L.head.right.right.right, 35);
L.head.right.right.right = L.push(L.head.right.right.right, 20);
 
# flatten the list
L.head = L.flatten(L.head);
 
L.printList()
# This code is contributed by maheshwaripiyush9


C#
// C# program for flattening a Linked List
using System;
public class List {
    Node head; // head of list
 
    /* Linked list Node */
    public
 
 
 class Node {
        public
 
 
 int data;
        public
 
 
 Node right, down;
 
        public
 
 
 Node(int data) {
            this.data = data;
            right = null;
            down = null;
        }
    }
 
    // An utility function to merge two sorted linked lists
    Node merge(Node a, Node b) {
        // if first linked list is empty then second
        // is the answer
        if (a == null)
            return b;
 
        // if second linked list is empty then first
        // is the result
        if (b == null)
            return a;
 
        // compare the data members of the two linked lists
        // and put the larger one in the result
        Node result;
 
        if (a.data < b.data) {
            result = a;
            result.down = merge(a.down, b);
        }
 
        else {
            result = b;
            result.down = merge(a, b.down);
        }
 
        result.right = null;
        return result;
    }
 
    Node flatten(Node root) {
        // Base Cases
        if (root == null || root.right == null)
            return root;
 
        // recur for list on right
        root.right = flatten(root.right);
 
        // now merge
        root = merge(root, root.right);
 
        // return the root
        // it will be in turn merged with its left
        return root;
    }
 
    /*
     * Utility function to insert a node at beginning of the linked list
     */
    Node Push(Node head_ref, int data) {
        /*
         * 1 & 2: Allocate the Node & Put in the data
         */
        Node new_node = new Node(data);
 
        /* 3. Make next of new Node as head */
        new_node.down = head_ref;
 
        /* 4. Move the head to point to new Node */
        head_ref = new_node;
 
        /* 5. return to link it back */
        return head_ref;
    }
 
    void printList() {
        Node temp = head;
        while (temp != null) {
            Console.Write(temp.data + " ");
            temp = temp.down;
        }
        Console.WriteLine();
    }
 
    /* Driver program to test above functions */
    public static void Main(String []args) {
        List L = new List();
 
        /*
         * Let us create the following linked list 5 -> 10 -> 19 -> 28 | | | | V V V V 7
         * 20 22 35 | | | V V V 8 50 40 | | V V 30 45
         */
 
        L.head = L.Push(L.head, 30);
        L.head = L.Push(L.head, 8);
        L.head = L.Push(L.head, 7);
        L.head = L.Push(L.head, 5);
 
        L.head.right = L.Push(L.head.right, 20);
        L.head.right = L.Push(L.head.right, 10);
 
        L.head.right.right = L.Push(L.head.right.right, 50);
        L.head.right.right = L.Push(L.head.right.right, 22);
        L.head.right.right = L.Push(L.head.right.right, 19);
 
        L.head.right.right.right = L.Push(L.head.right.right.right, 45);
        L.head.right.right.right = L.Push(L.head.right.right.right, 40);
        L.head.right.right.right = L.Push(L.head.right.right.right, 35);
        L.head.right.right.right = L.Push(L.head.right.right.right, 20);
 
        // flatten the list
        L.head = L.flatten(L.head);
 
        L.printList();
    }
}
 
// This code is contributed by umadevi9616


Javascript


输出:

5 7 8 10 19 20 20 22 30 35 40 45 50

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程