简体   繁体   English

使用Java对链表进行递归MergeSort

[英]Recursive MergeSort on a Linked List using Java

I searched on the net for a good clean and simple implentation of a merge sort algorithm in Java for a Linked List that uses recursion. 我在网上搜索了Java中合并排序算法的良好简洁方法,以发现使用递归的链表。

I couldn't find a nice one so Im trying to implement it here. 我找不到一个不错的,所以我试图在这里实现。 but Im stuck. 但我卡住了。

Here is what I have so far: 这是我到目前为止的内容:

public List mergeSortList(Node head, Node tail) {

    if ((head == null) || (head.next == null))
        return;

    Node middle = this.findMiddle(head);
    List left = mergeSortList(this.head, middle);
    List right = mergeSortList(middle.next, tail);
    return merge(left, right);
}

private List merge(List left, List right) {
    List returnedList = new LinkedList();

}

private Node findMiddle(Node n) {
    Node slow, fast;
    slow = fast = n;

    while (fast != null && fast.next.next != null) {
        slow = slow.next;
        fast = fast.next.next;
    }
    return slow;
}

Can someone help me correct any errors and fill the stubs please. 有人可以帮我纠正任何错误,请填写存根。

Thanks 谢谢

First error is in following :- 第一个错误是在下面:

while(fast != null && fast.next.next != null)
{
   slow = slow.next;
   fast = fast.next.next;
}  

fast.next can be null when you do fast.next.next , considering the case when no of elements is odd. 考虑到没有元素为奇数的情况, fast.next.nextfast.next可以为null。

Here is a modified code:- 这是修改后的代码:

while(fast != null && fast.next.next != null)
{
    slow = slow.next;
    if(fast.next!=null)
        fast = fast.next.next;
    else break;
}  

Here is another modification:- 这是另一个修改:

public List mergeSortList(Node head)
{
    if ( (head == null) || (head.next == null))
       return head;
    Node middle = this.findMiddle(head);
    Node first = head;
    Node second = middle.next;
    middle.next = null; 
    Node left = mergeSortList(first);
    Node right = mergeSortList(second);
    return merge(left, right);
 }

Explanation: You donot need to pass tail to the function, You can split the list at middle into two separate list ending with null. 说明:您不需要将tail传递给该函数,您可以将中间的列表分成两个以null结尾的单独列表。 And after recursion of two list just reconnect them to prevent loss of original list 递归两个列表后,只需重新连接它们,以防止丢失原始列表

Here is clean and simple implementation for Merge Sort on LinkedList 这是LinkedList上Merge Sort的干净简单的实现

public class MergeSortLinkedList {

static class Node {
    Node next;
    int value;

    Node(int value) {
        this.value = value;
    }
}

public static void main(String[] args) {
    Node head = new Node(10);
    head.next = new Node(5);
    head.next.next = new Node(2);
    head.next.next.next = new Node(1);
    head.next.next.next.next = new Node(6);
    head.next.next.next.next.next = new Node(8);
    head.next.next.next.next.next.next = new Node(3);
    head.next.next.next.next.next.next.next = new Node(2);

    print(head);

    Node sortedHead = mergeSort(head);
    print(sortedHead);
}

static void print(Node head) {
    Node tmp = head;
    while (tmp != null) {
        System.out.print(tmp.value + "->");
        tmp = tmp.next;
    }
    System.out.println();
}

static Node getMiddle(Node head) {
    if (head == null || head.next == null) {
        return head;
    }
    Node slow = head;
    Node fast = head;
    while (fast.next != null && fast.next.next != null) {
        fast = fast.next.next;
        slow = slow.next;
    }
    return slow;
}

static Node sortedMerge(Node left, Node right) {
    if (left == null) {
        return right;
    }
    if (right == null) {
        return left;
    }
    if (left.value < right.value) {
        left.next = sortedMerge(left.next, right);
        return left;
    } else {
        right.next = sortedMerge(left, right.next);
        return right;
    }
}

static Node mergeSort(Node head) {
    if (head == null || head.next == null) {
        return head;
    }
    Node middle = getMiddle(head);
    Node middleNext = middle.next;
    middle.next = null;
    Node left = mergeSort(head);
    Node right = mergeSort(middleNext);
    return sortedMerge(left, right);
}

} }

This looks like a good start. 这看起来是一个好的开始。 Your merge method is going to work just like any other merge sort implementation except you're dealing with lists instead of integers. 您的merge方法将像其他任何合并排序实现一样工作,除了您要处理列表而不是整数。

What you need to do is: 您需要做的是:

  • create a new list to return ('result') 创建一个新列表以返回(“结果”)
  • compare the first element in List 'left' to the first in List 'right' 比较列表“ left”中的第一个元素与列表“ right”中的第一个元素
  • copy the smaller element to the result 将较小的元素复制到结果中
  • advance your pointer into whichever list the smaller element came from 将您的指针前进到较小元素来自的任何列表
  • repeat until you hit the end of a list 重复直到您到达列表的末尾
  • copy all the remaining elements to the result 将所有其余元素复制到结果中

Take a stab at that (post your updated code) and we'll be happy to help you out more from there. 尝试一下(发布更新的代码),我们将很乐意为您提供更多帮助。

Solution divided in two methods, First method is recursive method what we call from main(), then divide list using fast and slow pointer technique (fast walks 2 step when slow walks one), now call itself recursively with both the lists, and combine returned list using second method mergeSortedList, also we are calling mergeSortedList again and again within the recursion, so at the very end when there is only one element left in each list, we compare them and add together in right order. 解决方案分为两种方法,第一种方法是递归方法,即我们从main()调用的方法,然后使用快速指针和慢速指针技术划分列表(慢速走一个时快走2步),现在用两个列表递归调用自身,并合并使用第二种方法mergeSortedList返回列表,我们也在递归中一次又一次地调用mergeSortedList,所以最后,当每个列表中只剩下一个元素时,我们将它们进行比较并以正确的顺序加在一起。

ListNode sortList(ListNode head) {
        if (head == null || head.next == null) return head;
        ListNode fast = head;
        ListNode slow = head;
        // get in middle of the list :
        while (fast.next!= null && fast.next.next !=null){slow = slow.next; fast = fast.next.next;}
        fast = slow.next;
        slow.next=null;
        return mergeSortedList(sortList(head),sortList(fast));
        }

ListNode mergeSortedList(ListNode firstList,ListNode secondList){
            ListNode returnNode = new ListNode(0);
            ListNode trackingPointer = returnNode;
            while(firstList!=null && secondList!=null){
                if(firstList.val < secondList.val){trackingPointer.next = firstList; firstList=firstList.next;}
                else {trackingPointer.next = secondList; secondList=secondList.next;}
                trackingPointer = trackingPointer.next;
            }
            if (firstList!=null) trackingPointer.next = firstList;
            else if (secondList!=null) trackingPointer.next = secondList;
            return returnNode.next;
            }
        }

Working solution in java. Java中的工作解决方案。 Go to the link below: 转到下面的链接:

http://ideone.com/4WVYHc http://ideone.com/4WVYHc

import java.util.*;
import java.lang.*;
import java.io.*;

class Node
{
    int data;
    Node next;

    Node(int data){
        this.data = data;
        next = null;
    }

    void append(Node head, int val){
        Node temp = new Node(val);
        Node cur = head;

        if(head == null)
        {
            return;
        }
        while(cur.next != null)
        {
            cur = cur.next;
        }
        cur.next = temp;
        return;

    }

    void display(){

        Node cur = this;
        while(cur != null)
        {
            System.out.print(cur.data + "->");
            cur = cur.next;
        }
    }
}

class Ideone
{
    public Node findMiddle(Node head){
        if(head == null )
            return null;

        Node slow, fast;
        slow = head;
        fast = head;

        while(fast != null && fast.next != null && fast.next.next != null){
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;

    }

    public Node merge(Node first, Node second){

        Node head = null;
        while(first != null && second != null){

            if(first.data < second.data){
                if(head == null){
                    head = new Node(first.data);
                }
                else
                    head.append(head,first.data);
                first = first.next;
            }
            else if(second.data < first.data){
                    if(head == null){
                    head = new Node(second.data);
                }
                else
                    head.append(head,second.data);
                second = second.next;
            }
            else{
                    if(head == null){
                        head = new Node(first.data);
                        head.append(head,second.data);
                    }
                    else{
                        head.append(head,first.data);
                        head.append(head,second.data);
                    }
                second = second.next;
                first = first.next;
            }
        }   
            while(first != null){
                if(head == null){
                    head = new Node(first.data);
                }
                else
                    head.append(head,first.data);
                first = first.next;
            }

                while(first != null){
                if(head == null){
                    head = new Node(first.data);
                }
                else
                    head.append(head,first.data);
                first = first.next;
                }

                while(second != null){
                if(head == null){
                    head = new Node(second.data);
                }
                else
                    head.append(head,second.data);
                second = second.next;
            }


        return head;    
    }

    public Node mergeSort(Node head){

        if(head == null)
            return null;

        if(head.next == null)
            return head;

        Node first = head;
        Node mid = findMiddle(first);
        Node second = mid.next;
        mid.next = null;
        Node left = mergeSort(first);
        Node right = mergeSort(second);
        Node result = merge(left, right);
        return result;

    }

    public static void main (String[] args) throws java.lang.Exception
    {
        Node head = new Node(5);
        head.append(head,1);
        head.append(head,5);
        head.append(head,1);
        head.append(head,5);
        head.append(head,3);
        System.out.println("Unsoreted linked list:");
        head.display();
        Ideone tmp = new Ideone();
        Node result = tmp.mergeSort(head);
        System.out.println("\nSorted linked list:");
        result.display();
    }
}

Below is the Java version of the post to sort numbers in linked list using merge sort. 以下是该帖子的Java版本,用于使用合并排序对链接列表中的数字进行排序。

import java.util.ArrayList;

public class SortNumbersInLinkedListUsingMergeSort {

    Node head;

    public static void main(String[] args) {
        SortNumbersInLinkedListUsingMergeSort sll = new SortNumbersInLinkedListUsingMergeSort();
        // creating an unsorted linked list
        sll.head = new Node(2);
        sll.head.next = new Node(5);
        sll.head.next.next = new Node(3);
        sll.head.next.next.next = new Node(-1);
        sll.head.next.next.next.next = new Node(1);
        printList(sll.head);
        sll.head = Merge(sll.head);
        printList(sll.head);
    }



    // 
    public static Node Merge(Node head){

        // if linked list has no or only one element then return
        if (head == null || head.next == null){
            return null;
        }

        // split the linked list into two halves, (front and back as two heads) 
        ArrayList<Node> list = splitIntoSublists(head);

        // Recursively sort the sub linked lists 
        Merge(list.get(0));
        Merge(list.get(1));

        // merge two sorted sub lists
        head = mergeTwoSortedLists(list.get(0), list.get(1));

        return head;


    }

    // method to merge two sorted linked lists
    public static Node mergeTwoSortedLists(Node front, Node back){

        Node result;

        if (front == null){
            return back;
        }

        if (back == null){
            return front;
        }

        if (front.data >= back.data){
            result = back;
            result.next = mergeTwoSortedLists(front, back.next);
        }
        else{
            result = front;
            result.next = mergeTwoSortedLists(front.next, back);
        }

        return result;
    }

    // method to split linked list into two list in middle.
    public static ArrayList<Node> splitIntoSublists(Node head){
        Node slowPointer;
        Node fastPointer ;

        Node front = null;
        Node back = null;

        ArrayList<Node> li = new ArrayList<Node>();

        if (head == null || head.next == null){
            front = head;
            back = null;
        }
        else{
            slowPointer= head;
            fastPointer = head.next;

            while (fastPointer != null && fastPointer.next != null){

                slowPointer = slowPointer.next;
                fastPointer = fastPointer.next.next;

            }

            front = head;
            back =  slowPointer.next;
            slowPointer.next = null;

        }

        li.add(front);
        li.add(back);
        return li;
    }

    // method to print linked list
    public static void printList(Node head){
        Node pointer = head;

        while (pointer != null){
            System.out.print(pointer.data + " ");
            pointer = pointer.next;
        }
        System.out.println();
    }

}

// class to define linked list 
class Node{
    int data;
    Node next;

    public Node (int data){
        this.data = data;
    }
}

Here is a working example : 这是一个工作示例:

public class MergeSort{
    public Node head = null;

    public class Node {
        int val;
        Node next;

        public Node () {//Constructor
            val = 0;
            next = null;
        }
        public Node (int i) { //constructor
            val = i;
            next = null;
        }


    }
    public void insert ( int i) { //inserts node at the beginning
        Node n = new Node(i);
        n.next = head;
        head = n;
    }

    public void printList (Node head) {
        while (head != null) {
            System.out.println (head.val);
            head = head.next;
        }
    }

    public Node sort (Node head) {
        if ( head == null || head.next ==null ) return head; // no need to sort if there's no node or only one node in the Linked List
        Node mid = find_Mid (head); // find middle of the LinkedList
        Node sHalf = mid.next ; mid.next = null; //Splitting into two linked lists
        Node  h = merge ( sort(head), sort(sHalf) ); //Call merge recursively
        return h;

    }

    public Node merge ( Node n1 , Node n2) {
        Node curr = null;

        if ( n1 == null )
            return n2; //n1 empty
        if ( n2 == null )
            return n1; // n2 empty


            if ( n1.val < n2.val ) { 

                 curr=n1; 
                 curr.next = merge (n1.next, n2); //Call merge recursively

            }
            else { 

                curr = n2; 
                curr.next = merge (n1, n2.next); //Call merge recursively
            }

        return curr;

    }

    public Node find_Mid (Node head) {
        Node slow = head; Node fast = head;

        while ( fast.next != null && fast.next.next != null ) {
            slow = slow.next;
            fast = fast.next.next;
        }

        return slow;
    }

     public static void main(String []args){
        System.out.println("Hello World");
        MergeSort m = new MergeSort ();
        m.insert ( 3 );
        m.insert ( 4 );
        m.insert ( 16 );
        m.insert ( 10 );
        m.insert ( 5 );
        m.insert ( 1 );
        m.insert ( -5 );
        m.printList(m.head);
        Node n = m.find_Mid (m.head);
        System.out.println("Middle is :" + n.val);
        m.head = m.sort(m.head);
        m.printList(m.head);

     }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM