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
.........无限循环
答案 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.");
会告诉你,排序实际上正在完成,问题是后来发生的。这是我们在拥有丰富的源代码级调试器之前使用的技术,而且今天对于调试服务,网页和其他不便于在调试器中运行的程序来说仍然非常方便。