【问题标题】:Recursive MergeSort on a Linked List using Java使用 Java 对链表进行递归合并排序
【发布时间】:2013-11-17 02:53:48
【问题描述】:

我在网上搜索了一个干净简单的 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;
}

谁能帮我纠正任何错误并填写存根。

谢谢

【问题讨论】:

    标签: java algorithm recursion linked-list mergesort


    【解决方案1】:

    第一个错误如下:-

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

    fast.next 可以在您执行 fast.next.next 时为空,考虑到没有奇数元素的情况。

    这是修改后的代码:-

    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结尾的单独列表。并且在两个列表的递归之后只需重新连接它们以防止原始列表丢失

    【讨论】:

    • 你不能在mergeSortList中做一个空的return语句。它需要返回一个列表。
    【解决方案2】:

    这里是 LinkedList 上合并排序的简洁实现

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

    }

    【讨论】:

      【解决方案3】:

      这看起来是一个好的开始。您的合并方法将像任何其他合并排序实现一样工作,除了您处理的是列表而不是整数。

      你需要做的是:

      • 创建要返回的新列表(“结果”)
      • 将 List 'left' 中的第一个元素与 List 'right' 中的第一个元素进行比较
      • 将较小的元素复制到结果中
      • 将指针移到较小元素来自的列表中
      • 重复直到到达列表的末尾
      • 将所有剩余元素复制到结果中

      尝试一下(发布您更新的代码),我们很乐意为您提供更多帮助。

      【讨论】:

      • 谢谢。同样对于递归,停止条件是必需的。那是长度 0 还是 1。我刚刚将它添加到我的代码中。
      • 当你到达一个长度为 1 的列表时,你可以放心地说它已排序并返回...无需继续排序 :)
      【解决方案4】:

      解决方案分为两种方法, 第一种方法是我们从 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;
                  }
              }
      

      【讨论】:

      • 请解释一下你做了什么
      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

        下面是 post 的 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;
            }
        }
        

        【讨论】:

          【解决方案7】:

          这是一个工作示例:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-06-05
            • 2011-02-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-03-20
            • 2018-01-04
            相关资源
            最近更新 更多