简体   繁体   English

双链列表在合并排序时卡住-Java

[英]doubly linked list gets stuck when it gets to merge sort - java

I'm storing a random generated numbers in a doubly linked list. 我将随机生成的数字存储在双链表中。 If there's more than 5 integers that are greater than 50, I'm going to merge sort the linkedlist. 如果有大于5的5个以上的整数,我将合并对链表的排序。 The problem is that the program work but when it gets to the merge sort part, it never terminates and I can't figure out why. 问题在于程序可以正常工作,但是当它到达合并排序部分时,它永远不会终止,我也不知道为什么。

Here's my code: The merge sort is implemented above my main. 这是我的代码:合并排序是在我的主体之上实现的。

        import java.util.Random;
        import java.util.Scanner;

    public class DLinkedList<E> {




  private static class DLinkedNode<E> {
         private int item;
         private DLinkedNode<E> prev;
         private DLinkedNode<E> next;

         private DLinkedNode(int rand) {
           item = rand;
           next = null;
           prev = null;
         }

     private DLinkedNode(E value, DLinkedNode<E> prev, DLinkedNode<E> next) {
       item = (int) value;
       this.next = next;
       this.prev = prev;
     }
   }
protected DLinkedNode<E> head;
protected int size;
private static Scanner in;

  private void verify(boolean mustBeTrue) {
    if (! mustBeTrue) {
      throw new java.lang.AssertionError("assertion error");
    }
  }

  private void checkInvariants() {

    verify((size == 0) == (head == null));
    verify(size >= 0);
    if (size == 0) {
      return;     // no more checks
    }
    int measuredSize = 0;
    DLinkedNode<E> node = head;
    do {
      node = node.next;
      measuredSize++;
    } while (node != head);
    verify(measuredSize == size);
  }


  public DLinkedList() {
    head = null;
    size = 0;
    // one of the constructor's jobs is to make sure that the invariants hold.
    checkInvariants();
  }


  public boolean add(int rand) {
    checkInvariants();
    DLinkedNode<E> newNode = new DLinkedNode<E>(rand);
    if (head == null) {
      head = newNode;
      newNode.next = head;
      newNode.prev = head;
    } else {
      DLinkedNode<E> tail = head.prev;
      tail.next = newNode;
      head.prev = newNode;
      newNode.next = head;
      newNode.prev = tail;
    }
    size++;
    checkInvariants();
    return true;
  }


  private DLinkedNode<E> nodeAtPosition(int index) {
    verify (index >= 0);
    DLinkedNode<E> result = head;
    while (index > 0) {
      result = result.next;
      index--;
    }
    verify (result != null);
    return result;
  }


  public int remove(int index) {
    checkInvariants();
    if ((index < 0) || (index >= size)) {
      String badIndex =
        new String ("index " + index + " must be between 0 and " + (size - 1));
      throw new IndexOutOfBoundsException(badIndex);
    }
    verify (head != null);
    int value = head.item;
    if (size == 1) {
      head = null;   // very simple!!
    } else {
      DLinkedNode<E> node = nodeAtPosition(index);
      value = node.item;             // return the value
      if (index == 0) {              // removing the head node
        head = node.next;            // new head node == old second node
      }
      node.prev.next = node.next;    // get this node out of the list
      node.next.prev = node.prev;
    }
    size--;
    checkInvariants();
    return value;
  }
//////////////////////////////// MERGE SORT
  public DLinkedNode<String> merge_sort(DLinkedNode<String> head) {
        if(head == null || head.next == null) { return head; }
        DLinkedNode<String> middle = getMiddle(head);      //get the middle of the list
        DLinkedNode<String> sHalf = middle.next; 
        middle.next = null;   //split the list into two halfs

        return merge(merge_sort(head),merge_sort(sHalf));  //recurse on that
    }

    //Merge subroutine to merge two sorted lists
    public DLinkedNode<String> merge(DLinkedNode<String> a, DLinkedNode<String> b) {
        DLinkedNode<String> dummyHead, curr; 
        dummyHead = new DLinkedNode<String>(size); 
        curr = dummyHead;
        while(a !=null && b!= null) {
            if(a.item <= b.item) { curr.next = a; a = a.next; }
            else { curr.next = b; b = b.next; }
            curr = curr.next;
        }
        curr.next = (a == null) ? b : a;
        return dummyHead.next;
    }

    //Finding the middle element of the list for splitting
    public DLinkedNode<String> getMiddle(DLinkedNode<String> head) {
        if(head == null) { return head; }
        DLinkedNode<String> slow, fast; slow = fast = head;
        while(fast.next != null && fast.next.next != null) {
            slow = slow.next; fast = fast.next.next;
        }
        return slow;
    }
  //////////////////////////////////////////////// 

  public String toString() {
    checkInvariants();
    DLinkedNode<E> node = head;
    StringBuffer result = new StringBuffer();
    if (head != null) {
      while (true) {
        result.append (node.item);
        node = node.next;
        if (node == head) {
          break;    // entire list has been traversed
        }
        result.append (" ==> ");
      }
    }
    checkInvariants();   // make sure we didn't break anything
    return result.toString();
  }






  public static void main (String [] arguments) {

        Random rnd = new Random();
        in = new Scanner(System.in);
        int listCount;
        int countgrtr50=0;

        DLinkedList<String> dll = new DLinkedList<String>();
        System.out.println (dll);

        System.out.print("Enter number of integers: "); 
        listCount = in.nextInt();
        System.out.print("Enter range: "); 
        int range = in.nextInt();
        for (int i = 0; i < listCount; i++)
        {
            int rand = rnd.nextInt(range)+1;
            dll.add(rand); 
            if(rand>50){
            countgrtr50++;
            }
        }
        System.out.println (dll);
        System.out.println ("more than 50: " + countgrtr50 );

        if (countgrtr50>5){
            System.out.println ("sorting... ");

            dll.merge_sort(dll.head);
            //dll.remove(1);
            System.out.println ("after: "+dll);
        } else {
            // error if less than 5
            dll.remove(4);
            System.out.println ("else after: "+dll);
        }

      }



}

This is the result I get: 这是我得到的结果:

Enter number of integers: 20
Enter range: 100
60 ==> 36 ==> 12 ==> 44 ==> 11 ==> 61 ==> 27 ==> 86 ==> 55 ==> 51 ==> 5 ==> 44 ==> 39 ==> 18 ==> 23 ==> 50 ==> 73 ==> 49 ==> 96 ==> 82
more than 50: 8
sorting... 

and then it doesn't terminate, but when the integers greater than 50 are less than 5, it works fine cause it doesn't sort or anything. 然后它不会终止,但是当大于50的整数小于5时,它会正常工作,因为它不进行排序或其他任何操作。

Because sometimes you assume your list is circular, and sometimes not. 因为有时您认为列表是循环的,有时则不是。 In your add, checkInvariants and toString methods, you assume head comes after tail (tail.next = head and head.prev = tail). 在您的add,checkInvariants和toString方法中,您假定head在tail之后(tail.next = head和head.prev = tail)。 However, in your merge and getMiddle methods, you assume that null comes after tail (tail.next = null). 但是,在您的merge和getMiddle方法中,您假定null出现在尾部之后(tail.next = null)。 That's why your getMiddle methods ends up in an infinite loop, as neither fast.next nor fast.next.next becomes null. 这就是为什么您的getMiddle方法最终陷入无限循环的原因,因为fast.next和fast.next.next都不为空。

My suggestion is, make your head.prev = null and tail.prev = null. 我的建议是,使您的head.prev = null和tail.prev = null。 Also, you should have a reference to tail when building a doubly linked list. 另外,在构建双向链表时,应该对tail进行引用。

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

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