for (Event e : pq)
不按优先顺序进行迭代。
while(!pq.isEmpty()){
Event e = pq.poll();
}
这可行,但会清空队列。
答案 0 :(得分:24)
来自Javadocs:
方法
iterator()
中提供的迭代器不保证以任何特定顺序遍历PriorityQueue的元素。如果您需要有序遍历,请考虑使用Arrays.sort(pq.toArray())
。
可能还有其他等效机制。
答案 1 :(得分:22)
由于底层实现(我认为它是Java中的min-heap),因此无法按顺序遍历优先级队列。它不是一个排序数组,因此您可以从一个元素转到具有较低优先级的元素。 偷看是恒定的时间,因为它看着最小的元素。要获得下一个(在O(log n)时间内),必须将最小元素出列,这就是它的工作原理。 Dequeing不仅仅是将该元素排除在外,底层结构重新排列,以便首先将元素放在最低优先级。
此外,遍历整个优先级队列的是O(n log(n))操作。所以你也可以抓住队列中的所有元素并对它们进行排序(也是O(n log(n))),然后你可以按照自己的意愿进行排序。唯一的缺点是你持有队列的额外副本。
尽管如此,如果您需要以这种方式遍历数据,优先级队列可能不是满足您需求的正确数据结构。
答案 2 :(得分:8)
基于堆的优先级队列仅保证第一个元素是最高/最低。没有便宜的(即O(n))方式来获得排序形式的元素。
如果您需要经常这样做,请考虑使用以排序形式维护元素的结构。例如,使用java.util.TreeSet
,并使用pollFirst()
或pollLast()
代替peek()
/ poll()
答案 3 :(得分:1)
以前的海报说过一切,但没有人提供完整的工作示例(除了复制pq),所以这里是:
Event[] events = pq.toArray(new Event[pq.size()]);
Arrays.sort(events, pq.comparator());
for (Event e : events) {
System.out.println(e);
}
答案 4 :(得分:0)
最近,我遇到了同样的问题。我想使用优先级队列中的某个特定对象,然后保留剩余的元素。
1)我创建了一个newPriorityQueue。 2)使用Iterator解析oldQueue中的每个元素 3)使用oldQueue.poll()方法检索元素 4)如果不使用,则将元素3)插入newPriorityQueue。
Queue<String> newQueue = new PriorityQueue<String>();
// Assuming that oldQueue have some data in it.
Iterator<String> itr = oldQueue.iterator();
while(itr.hasNext()){
String str = oldQueue.poll();
// do some processing with str
if(strNotUsed){
newQueue.offer(str);
}
}
最后,oldQueue将为空。 @其他: - 如果我可以做同样的事情,请建议一个更好的方法。我不能使用迭代器,因为它不会以正确的顺序返回元素。
答案 5 :(得分:0)
您可以在循环中创建队列和轮询的副本,在此示例中,pq是原始优先级队列:
PriorityQueue<Your_class> pqCopy = new PriorityQueue<Your_class>(pq);
while(!pqCopy.isEmpty()){
Your_Class obj = pqCopy.poll();
// obj is the next ordered item in the queue
.....
}
答案 6 :(得分:0)
因此,如上所述,将PriorityQueue放在List中然后对其进行排序是一个不错的选择。以下是迭代器给出意外结果的一些细节:
迭代器不会以正确的顺序返回元素,因为它从底层数据结构打印(类似于ArrayList)。 ArrayList以与BinaryHeap的Array实现中存储数据相同的方式存储数据。例如:
PriorityQueue<Integer> pq = new PriorityQueue<>();
ArrayList<Integer> test = new ArrayList(Arrays.asList(6,12,7,9,2));
test.forEach(x -> pq.add(x));
System.out.println("Priority Queue:- "+pq); [2, 6, 7, 12, 9]
其中childOf(i)是2 * i + 1和2 * i + 2而parentOf(i)是(i-1)/ 2
答案 7 :(得分:-1)
peek()
方法不会从队列中删除任何内容,但由于这个原因,它会不断获取最高值,直到它为空。
我猜你在你的while循环后检查它是否为空,这会给你这个结论。
这样做的唯一方法是自己排序。 您可以像这样获得原始比较器:
Event[] events = Arrays.sort(pq.toArray(), pq.comparator());
for (Event e : events) {
// do stuff
}
答案 8 :(得分:-2)
for (Event event: pq.toArray(new Event[pq.size()])) {
event.toString();
}