在Java中排序优先级队列
我试图在PriorityQueue
插入整数,我知道:
如果在构造PriorityQueue
时未指定比较器,则使用存储在队列中的数据类型的默认比较器。 默认比较器将按升序对队列进行排序
但是,我得到的输出不是按排序顺序。 运行以下代码后的输出为: [2, 4, 8, 6]
public static void main(String args[]) { PriorityQueue q = new PriorityQueue(10); q.offer(4); q.offer(2); q.offer(8); q.offer(6); System.out.print(q); }
有人可以解释一下原因吗?
PriorityQueue就是所谓的二进制堆 。 它只是在第一个元素最少的意义上排序/排序。 换句话说,它只关心队列前面的内容,其余部分在需要时“排序”。
元素仅在它们出列时排序,即使用poll()
从队列中删除。 这就是为什么PriorityQueue能够获得如此优异的性能的原因,因为它不会在任何时候进行任何更多的排序。
如果你想知道堆是如何工作的,我推荐麻省理工学院的这个讲座 。
当您在PriorityQueue
上调用System.out.print()
时,它不会从中poll()
您的元素,而是调用toString()
。 PriorityQueue
没有实现toString()
,所以它是来自AbstractCollection
的toString()
,它将被调用:
public String toString() { Iterator i = iterator(); if (! i.hasNext()) return "[]"; StringBuilder sb = new StringBuilder(); sb.append('['); for (;;) { E e = i.next(); sb.append(e == this ? "(this Collection)" : e); if (! i.hasNext()) return sb.append(']').toString(); sb.append(", "); } }
如您所见,此方法仅迭代PriorityQueue
。 正如您在PriorityQueue
javadoc中看到的:
方法iterator()中提供的迭代器不保证以任何特定顺序遍历优先级队列的元素。 如果需要有序遍历,请考虑使用Arrays.sort(pq.toArray())。
如果您希望使用PriorityQueue
因为它有意使用,您必须poll()
每个值并打印它:
while (!q.isEmpty()) { Integer i = q.poll(); System.out.println(i); }
输出:
2 4 6 8
那是因为java.util.PriorityQueue
实现了二进制堆 。
不幸的是,没有简单的方法来排序PriorityQueue。 如果poll()
对象直到队列为空,则元素将按比较器的顺序排列。 这就是为什么当我遇到类似的问题时,我已经实现了自己的堆类,允许我在事后对元素进行排序; 我用于大量元素的前N列表。
(由于我在课堂上上课,我没有权利在这里发布,但它主要是在python的heap.py
之后建模的,所以有很好的灵感来源)
无界优先级队列基于priority heap
Priority Queue.Offer()
方法在内部使用siftUpComparable()
在没有比较器的情况下传递项目
siftUpComparable
将当前元素与Parent Positions( int i = paramInt - 1 >>> 1;
)中的所有元素进行比较int i = paramInt - 1 >>> 1;
直到满足Heap条件
Nutshell中的siftUpComparable
算法(如果通过数组Root = index 0实现):
1.Add the element to the bottom level of the heap. 2.Compare the added element with its parent; if they are in the correct order, stop. 3.If not, swap the element with its parent and return to the previous step.
Java代码
private void siftUpComparable(int paramInt, E paramE) { Comparable localComparable = (Comparable)paramE; while (paramInt > 0) { int i = paramInt - 1 >>> 1; Object localObject = this.queue[i]; if (localComparable.compareTo(localObject) >= 0) { break; } this.queue[paramInt] = localObject; paramInt = i; } this.queue[paramInt] = localComparable; }
在你的例子中:
q.offer(4);
– >插入4
Result: PQ[0]=4
q.offer(2);
– > siftUpComparable
比较4到2并交换位置(在父位置进行比较)
Result: PQ[0]=2,PQ[1]=4
q.offer(8);
– > siftUpComparable
比较8和2(因为2位于父位置)
Result: PQ[2]=8
q.offer(6);
: – > siftUp比较6和4(位置3的父级是位置1根据paramInt - 1 >>> 1;
逻辑)
Result: PQ[3]=6
最终PQ=[2, 4, 8, 6]
java优先级队列如何工作?
基本上,您的print语句不会按顺序遍历树。
- 为什么以下代码转换为java字节码中的新+ dup op指令?
- Spring Boot测试中的MockBean注释导致NoUniqueBeanDefinitionException
- Spring MVC何时会自动生成HttpSession?
- ‘str = new String(bytes,“UTF8”)’和’bytes = str.getBytes(“UTF8”)’中的字节值不一样
- 可滚动的JPanel
- 我有一个条形图,我想更新,我尝试了revalidate和重绘方法,但没有成功
- 如何发出和处理自定义事件?
- 无法使用JAVA从网站提取xml数据
- java.lang.ClassCastException:java.lang.Class无法强制转换为java.lang.reflect.ParameterizedType