如何迭代PriorityQueue?

时间:2011-11-14 22:29:33

标签: java collections loops priority-queue

for (Event e : pq)

不按优先顺序进行迭代。

while(!pq.isEmpty()){
  Event e = pq.poll();
}

这可行,但会清空队列。

9 个答案:

答案 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();
}