使用优先级队列排序链表

时间:2018-01-21 19:00:59

标签: java algorithm linked-list priority-queue

public class SortList{
   class ListNode{
      ListNode next;
      int val;

    public ListNode(int val){
      this.val = val;
     }
}   
public static ListNode sortList(ListNode head) {
    if(head == null)
        return null;
    PriorityQueue<ListNode> pq = new PriorityQueue<ListNode>( (a,b) -> (a.val - b.val));
    while(head != null){
        pq.add(head);
        head = head.next;
    }
    ListNode pointer = pq.poll();
    ListNode result = pointer;
    while(pq.size() >0 ){
    System.out.println(pq.size());
        ListNode nextTemp = pq.poll();
        pointer.next = nextTemp;
        pointer = pointer.next;
    }
    return result;
}
  public static void main(String[] args){ 
  ListNode head = new ListNode(3);
  ListNode n2 = new ListNode(2);
  ListNode n3 = new ListNode(5);
  ListNode n4 = new ListNode(9);
  ListNode n5 = new ListNode(7);
  ListNode n6 = new ListNode(4);
  head.next = n2;
  n2.next = n3;
  n3.next = n4;
  n4.next = n5;
  n5.next = n6;
  n6.next = null;
  ListNode result = sortList(head);
   while(result != null){
   System.out.println(result.val);
   result = result.next;
    }
  }
 }

我想使用优先级队列对链表进行排序,但为什么我在poll()之前得到一个无限循环,直到队列为空?列表大小减小但增加,优先级队列永远不会为空。

输出:

6
5
4
3
2
1
1
2
3
4
6
7
9
2
3
4
6
7
9
2
3
4
6
7
9
2
3
4
6
7
9
2
3
4
6

.........无限循环

1 个答案:

答案 0 :(得分:1)

让我们来看看你的输出:

6
5
4
3
2
1  Up to this point, you're removing items from the priority queue
1  This is the first item in the sorted list output
2
3
4
6
7
9  End of the sorted list output
2  ?? This happens because 9 is pointing to 2 in the original list.
3
4
6
7
9

从输出中可以清楚地看出,您运行的代码与您发布的代码不同。我知道这是因为输出不包含值“5”,输出中有7个不同的项目,但代码中只有6个。

您的无限循环不在优先级队列中。您可以通过修改main()来证明这一点,以便在开始编写列表时输出消息,如下所示:

ListNode result = sortList(head);
System.out.println("Sorted list is:"); // start output
while(result != null){
    System.out.println(result.val);
    result = result.next;
}

正如我在评论中指出的那样,问题是优先级队列中的最后一项具有非空next指针。因此,当您将其删除并将其添加到结果列表中时,您最终会得到一个循环。结果列表最终看起来像这样:

1 -> 2 -> 3 -> 4 -> 6 -> 7 -> 9 ->
     ^                            \
      \                           /
       <-----<---------<--------<-

要解决此问题,请修改您的sortList方法,以便将列表中最后一项的next指针设置为null

while(pq.size() >0 ){
    System.out.println(pq.size());
    ListNode nextTemp = pq.poll();
    pointer.next = nextTemp;
    pointer = pointer.next;
}

pointer.next = null;  // terminate the list!!
return result;

使用调试器很容易诊断出这种错误。您可以单步执行代码以查看完全它正在做什么,并且您可以设置断点,以便代码将停止在特定行执行。如果您使用调试器,您可能在几分钟内就发现了这个问题。如果你不知道如何使用它,请学习。现在

诊断这些问题的另一种方法是放置输出语句,如我所示。一个简单的System.out.println("Finished the sort.");会告诉你,排序实际上正在完成,问题是后来发生的。这是我们在拥有丰富的源代码级调试器之前使用的技术,而且今天对于调试服务,网页和其他不便于在调试器中运行的程序来说仍然非常方便。