📜  Java程序合并两个排序列表(就地)

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

Java程序合并两个排序列表(就地)

给定两个排序列表,将它们合并以产生一个组合排序列表(不使用额外空间)。
例子:

Input: head1: 5->7->9
        head2: 4->6->8 
Output: 4->5->6->7->8->9
Explanation: The output list is in sorted order.

Input: head1: 1->3->5->7
        head2: 2->4
Output: 1->2->3->4->5->7
Explanation: The output list is in sorted order.

下面的帖子中有不同的讨论不同的解决方案。
合并两个排序的链表

方法1(递归):

方法:给定链表已排序,可以形成递归解决方案。

  1. 比较两个链表的头部。
  2. 在两个头节点中找到较小的节点。当前元素将是两个头节点中较小的节点。
  3. 两个列表的其余元素将在此之后出现。
  4. 现在运行一个带有参数的递归函数、较小元素的下一个节点和另一个头。
  5. 递归函数将返回与排序元素的其余部分链接的下一个较小元素。现在将当前元素的下一个指向该元素,即curr_ele->next=recursivefunction()
  6. 处理一些极端情况。
    • 如果两个头都为 NULL,则返回 null。
    • 如果一个头为空,则返回另一个。
Java
// Java program to merge two sorted
// linked lists in-place.
class GFG 
{
    static class Node 
    {
        int data;
        Node next;
    };
  
    // Function to create newNode in 
    // a linkedlist
    static Node newNode(int key)
    {
        Node temp = new Node();
        temp.data = key;
        temp.next = null;
        return temp;
    }
  
    // A utility function to print 
    // linked list
    static void printList(Node node)
    {
        while (node != null) 
        {
            System.out.printf("%d ", 
                              node.data);
            node = node.next;
        }
    }
  
    // Merges two given lists in-place. 
    // This function mainly compares head 
    // nodes and calls mergeUtil()
    static Node merge(Node h1, Node h2)
    {
        if (h1 == null)
            return h2;
        if (h2 == null)
            return h1;
  
        // start with the linked list
        // whose head data is the least
        if (h1.data < h2.data) 
        {
            h1.next = merge(h1.next, h2);
            return h1;
        }
        else 
        {
            h2.next = merge(h1, h2.next);
            return h2;
        }
    }
  
    // Driver program
    public static void main(String args[])
    {
        Node head1 = newNode(1);
        head1.next = newNode(3);
        head1.next.next = newNode(5);
  
        // 1.3.5 LinkedList created
        Node head2 = newNode(0);
        head2.next = newNode(2);
        head2.next.next = newNode(4);
  
        // 0.2.4 LinkedList created
        Node mergedhead = merge(head1, head2);
  
        printList(mergedhead);
    }
}
// This code is contributed by Arnab Kundu


Java
// Java program to merge two sorted
// linked lists in-place.
class GfG 
{
    static class Node 
    {
        int data;
        Node next;
    }
  
    // Function to create newNode in 
    // a linkedlist
    static Node newNode(int key)
    {
        Node temp = new Node();
        temp.data = key;
        temp.next = null;
        return temp;
    }
  
    // A utility function to print 
    // linked list
    static void printList(Node node)
    {
        while (node != null) 
        {
            System.out.print(node.data + 
                             " ");
            node = node.next;
        }
    }
  
    // Merges two lists with headers as 
    // h1 and h2. It assumes that h1's 
    // data is smaller than or equal to 
    // h2's data.
    static Node mergeUtil(Node h1, Node h2)
    {
        // if only one node in first list
        // simply point its head to second 
        // list
        if (h1.next == null) 
        {
            h1.next = h2;
            return h1;
        }
  
        // Initialize current and next 
        // pointers of both lists
        Node curr1 = h1, next1 = h1.next;
        Node curr2 = h2, next2 = h2.next;
  
        while (next1 != null && 
               curr2 != null) 
        {
            // if curr2 lies in between curr1 
            // and next1 then do curr1->curr2->next1
            if ((curr2.data) >= (curr1.data) && 
                (curr2.data) <= (next1.data)) 
            {
                next2 = curr2.next;
                curr1.next = curr2;
                curr2.next = next1;
  
                // now let curr1 and curr2 to point
                // to their immediate next pointers
                curr1 = curr2;
                curr2 = next2;
            }
            else 
            {
                // if more nodes in first list
                if (next1.next != null) 
                {
                    next1 = next1.next;
                    curr1 = curr1.next;
                }
  
                // else point the last node of 
                // first list to the remaining 
                // nodes of second list
                else 
                {
                    next1.next = curr2;
                    return h1;
                }
            }
        }
        return h1;
    }
  
    // Merges two given lists in-place. 
    // This function mainly compares head 
    // nodes and calls mergeUtil()
    static Node merge(Node h1, Node h2)
    {
        if (h1 == null)
            return h2;
        if (h2 == null)
            return h1;
  
        // start with the linked list
        // whose head data is the least
        if (h1.data < h2.data)
            return mergeUtil(h1, h2);
        else
            return mergeUtil(h2, h1);
    }
  
    // Driver code
    public static void main(String[] args)
    {
        Node head1 = newNode(1);
        head1.next = newNode(3);
        head1.next.next = newNode(5);
  
        // 1->3->5 LinkedList created
        Node head2 = newNode(0);
        head2.next = newNode(2);
        head2.next.next = newNode(4);
  
        // 0->2->4 LinkedList created
        Node mergedhead = merge(head1, 
                                head2);
        printList(mergedhead);
    }
}
// This code is contributed by prerna saini


输出:

0 1 2 3 4 5 

复杂性分析:

  • 时间复杂度: O(n)。
    只需要遍历一次链表。
  • 辅助空间: O(n)。
    如果考虑递归堆栈空间。

方法2(迭代):

方法:这种方法与上述递归方法非常相似。

  1. 从头到尾遍历列表。
  2. 如果第二个列表的头节点位于第一个列表的两个节点之间,则将其插入其中并使第二个列表的下一个节点成为头。继续此操作,直到两个列表中都没有节点,即遍历两个列表。
  3. 如果第一个列表在遍历时到达末尾,则将下一个节点指向第二个列表的头部。

注意:比较两个列表,其中头部值较小的列表是第一个列表。

Java

// Java program to merge two sorted
// linked lists in-place.
class GfG 
{
    static class Node 
    {
        int data;
        Node next;
    }
  
    // Function to create newNode in 
    // a linkedlist
    static Node newNode(int key)
    {
        Node temp = new Node();
        temp.data = key;
        temp.next = null;
        return temp;
    }
  
    // A utility function to print 
    // linked list
    static void printList(Node node)
    {
        while (node != null) 
        {
            System.out.print(node.data + 
                             " ");
            node = node.next;
        }
    }
  
    // Merges two lists with headers as 
    // h1 and h2. It assumes that h1's 
    // data is smaller than or equal to 
    // h2's data.
    static Node mergeUtil(Node h1, Node h2)
    {
        // if only one node in first list
        // simply point its head to second 
        // list
        if (h1.next == null) 
        {
            h1.next = h2;
            return h1;
        }
  
        // Initialize current and next 
        // pointers of both lists
        Node curr1 = h1, next1 = h1.next;
        Node curr2 = h2, next2 = h2.next;
  
        while (next1 != null && 
               curr2 != null) 
        {
            // if curr2 lies in between curr1 
            // and next1 then do curr1->curr2->next1
            if ((curr2.data) >= (curr1.data) && 
                (curr2.data) <= (next1.data)) 
            {
                next2 = curr2.next;
                curr1.next = curr2;
                curr2.next = next1;
  
                // now let curr1 and curr2 to point
                // to their immediate next pointers
                curr1 = curr2;
                curr2 = next2;
            }
            else 
            {
                // if more nodes in first list
                if (next1.next != null) 
                {
                    next1 = next1.next;
                    curr1 = curr1.next;
                }
  
                // else point the last node of 
                // first list to the remaining 
                // nodes of second list
                else 
                {
                    next1.next = curr2;
                    return h1;
                }
            }
        }
        return h1;
    }
  
    // Merges two given lists in-place. 
    // This function mainly compares head 
    // nodes and calls mergeUtil()
    static Node merge(Node h1, Node h2)
    {
        if (h1 == null)
            return h2;
        if (h2 == null)
            return h1;
  
        // start with the linked list
        // whose head data is the least
        if (h1.data < h2.data)
            return mergeUtil(h1, h2);
        else
            return mergeUtil(h2, h1);
    }
  
    // Driver code
    public static void main(String[] args)
    {
        Node head1 = newNode(1);
        head1.next = newNode(3);
        head1.next.next = newNode(5);
  
        // 1->3->5 LinkedList created
        Node head2 = newNode(0);
        head2.next = newNode(2);
        head2.next.next = newNode(4);
  
        // 0->2->4 LinkedList created
        Node mergedhead = merge(head1, 
                                head2);
        printList(mergedhead);
    }
}
// This code is contributed by prerna saini

输出:

0 1 2 3 4 5 

复杂性分析:

  • 时间复杂度: O(n)。
    因为只需要遍历一次链表。
  • 辅助空间: O(1)。
    因为不需要空间。

有关更多详细信息,请参阅有关合并两个排序列表(就地)的完整文章!