Java PriorityQueue在删除元素时更改顺序
在不提供自定义比较器的情况下,优先级队列按升序插入元素,但是,在删除特定元素后,顺序会发生更改Java PriorityQueue在删除元素时更改顺序,java,data-structures,priority-queue,Java,Data Structures,Priority Queue,在不提供自定义比较器的情况下,优先级队列按升序插入元素,但是,在删除特定元素后,顺序会发生更改 PriorityQueue pq=new PriorityQueue(); pq.增加(10); pq.增加(1); pq.增加(2); pq.增加(2); pq.移除(2); 用于(int x:pq){ 系统输出println(x); } //产出:1102,而不是预期的:1210 有什么想法吗 谢谢。不要像在集合/数组上那样迭代您的优先级队列;使用.poll(),而不是: while(pq.pe
PriorityQueue pq=new PriorityQueue();
pq.增加(10);
pq.增加(1);
pq.增加(2);
pq.增加(2);
pq.移除(2);
用于(int x:pq){
系统输出println(x);
}
//产出:1102,而不是预期的:1210
有什么想法吗
谢谢。不要像在集合/数组上那样迭代您的
优先级队列
;使用.poll()
,而不是:
while(pq.peek()!=null){
System.out.println(pq.poll());
}
优先级队列是一种抽象数据类型,通常被实现为数据结构,而数据结构(通常)是通过数组实现的。
实现二进制堆还有其他一些方法,但普通数组是实现二进制堆的最快、最简单和最好的方法
数组如何表示二进制堆的示例如下:在您的情况下,队列顺序没有更改;相反,您只是以错误的方式使用了数据结构,只是以传统的
迭代方式对每个/迭代方式对其进行迭代,就像在基本数组上进行迭代一样,没有考虑到优先级队列支持数组没有按其第i个索引进行排序;相反,它将顶层元素保持在树的顶部(最小堆或最大堆大小写),您不能通过传统方式对其进行迭代来获得.poll()
效果。这是因为PriorityQueue是最小堆的实现(默认情况下在Java中),这意味着根元素将始终低于列表中的其他元素
以您的问题为例:
在数组中插入10时,索引1处的元素为10
插入1时,位置1处的元素现在为1,而位置10处的元素移到了索引2
插入2时,如1<2
所示,无需移动元素,2插入到索引3处
当您插入2时,2将位于10下方,因为需要移位,2将插入到2处,10将隐藏到索引4中
插入所有阵列后,请查看以下视频:
array: [NULL, 1, 2, 2, 10]
现在,当您删除2时,10需要移位,10被移回索引2,数组的状态是[NULL,1,10,2]
,这就是您迭代时看到的输出。此外,请检查PriorityQueue内部实现的,并且在未提供比较器时使用的
private void siftUpComparable(int k, E x) {
Comparable<? super E> key = (Comparable<? super E>) x;
while (k > 0) {
int parent = (k - 1) >>> 1;
Object e = queue[parent];
if (key.compareTo((E) e) >= 0)
break;
queue[k] = e;
k = parent;
}
queue[k] = key;
}
private void(int k,E x){
比较有趣。即使使用迭代器,它也会显示为1102
,有什么原因可以解释输出与.poll()之间的差异吗
?请参阅我对问题的评论谢谢,这就解释了它!也许可以将该评论移到您的答案中?这是对所选实现的一个很好的解释,但真正的答案是PriorityQueue的公共文档回答了这个问题(无论所选的实现是什么):“方法迭代器()中提供的迭代器”不保证以任何特定顺序遍历优先级队列的元素。”另外,实际的存储阵列backingPriorityQueue
本质上是一个堆/树结构。迭代该阵列(这就是增强型for each在此处的计算方式)将按元素的存储顺序迭代元素,而不是按元素在堆中的遍历方式迭代元素。因此,对于普通人来说,它本质上是一个“无序”数组。但这并不意味着队列相关方法(如#poll
,请参见下文)是无序的。答案就在javadoc for PriorityQueue中:“方法迭代器()中提供的迭代器不保证以任何特定顺序遍历优先级队列的元素。”