【问题标题】:PriorityQueue did not order its content correctly? [duplicate]PriorityQueue 没有正确排序其内容? [复制]
【发布时间】:2013-11-06 10:58:00
【问题描述】:

Java 文档说: 创建一个具有默认初始容量 (11) 的 PriorityQueue,它根据元素的自然排序对其进行排序。

但是当我写一些这样的测试时:

public class Test {

    public static void main (String a[]) {
        Queue<Integer> queue = new PriorityQueue<Integer>();

        for (int i = 1; i <= 20; i++) {
            queue.offer(i);
        }

        System.out.println(queue);

        Queue<Integer> queue2 = new PriorityQueue<Integer>();

        for (int i = 20; i >= 1; i--) {
            queue2.offer(i);
        }

        System.out.println(queue2);
    }
}

我得到以下输出:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
[1, 2, 7, 4, 3, 10, 8, 11, 5, 12, 13, 19, 15, 16, 9, 20, 14, 17, 6, 18]

看起来好像两个队列具有相同的内容,它们的内容没有得到相同的顺序?

【问题讨论】:

标签: java


【解决方案1】:

优先级队列不能保证完整集合的顺序;它只保证最小的元素在前面(或最大的,如果它是最大优先级队列)。

来自文档:

方法 iterator() 中提供的迭代器不能保证 以任何特定顺序遍历优先级队列的元素。 如果您需要有序遍历,请考虑使用 Arrays.sort(pq.toArray())。

也许要添加一点上下文:优先级队列内部所做的是将元素存储在对数高度的树结构中(无论如何在使用树的合理实现中)。 insert 和 remove-like 操作旨在将最小元素保留在该树的根部,并使每个子树中的元素大于父顶点的元素(这就是使它们成为堆的原因,该属性称为堆属性)。它不保证对作为兄弟的子树的元素进行任何排序,例如我们从排序树中所知道的。堆属性与对数高度一起为优先级队列提供了快速操作运行时间,但它的缺点是您只能快速获得一个元素,这是最小的一个(或最大堆的最大一个)。

【讨论】:

  • (因此,如果你重复poll() queue2 实例,你会得到排序的元素)
  • 这里只是补充一点颜色,Java的优先级队列实现是基于优先级堆的。通过阅读堆可以更好地理解优先级队列的行为。 en.wikipedia.org/wiki/Heap_(data_structure)
  • @Slanec:是的,这将被排序,并且该过程有时被称为HeapSort,这是因为优先级队列通常被实现为具有一些排序不变性的堆。
  • 非常感谢您的解释。似乎当 offer() 时,从 1 到 20 的项目构造了一棵树,该树与反向构造的树不同。我会花一些时间来查看您在此处发布的 wiki 页面。再次感谢,伙计们。
【解决方案2】:

PriorityQueue.toString 使用 iterator() 不能保证以任何特定顺序遍历优先级队列的元素(来自 API)。试试看

    while(!queue.isEmpty()) {
            System.out.print(queue.poll() + ",");
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-30
    • 2020-04-26
    • 2014-09-07
    相关资源
    最近更新 更多