簡體   English   中英

使用Java對鏈表進行遞歸MergeSort

[英]Recursive MergeSort on a Linked List using Java

我在網上搜索了Java中合並排序算法的良好簡潔方法,以發現使用遞歸的鏈表。

我找不到一個不錯的,所以我試圖在這里實現。 但我卡住了。

這是我到目前為止的內容:

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;
}

有人可以幫我糾正任何錯誤,請填寫存根。

謝謝

第一個錯誤是在下面:

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

考慮到沒有元素為奇數的情況, fast.next.nextfast.next可以為null。

這是修改后的代碼:

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

這是另一個修改:

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);
 }

說明:您不需要將tail傳遞給該函數,您可以將中間的列表分成兩個以null結尾的單獨列表。 遞歸兩個列表后,只需重新連接它們,以防止丟失原始列表

這是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);
}

}

這看起來是一個好的開始。 您的merge方法將像其他任何合並排序實現一樣工作,除了您要處理列表而不是整數。

您需要做的是:

  • 創建一個新列表以返回(“結果”)
  • 比較列表“ left”中的第一個元素與列表“ right”中的第一個元素
  • 將較小的元素復制到結果中
  • 將您的指針前進到較小元素來自的任何列表
  • 重復直到您到達列表的末尾
  • 將所有其余元素復制到結果中

嘗試一下(發布更新的代碼),我們將很樂意為您提供更多幫助。

解決方案分為兩種方法,第一種方法是遞歸方法,即我們從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;
            }
        }

Java中的工作解決方案。 轉到下面的鏈接:

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();
    }
}

以下是該帖子的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;
    }
}

這是一個工作示例:

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