16

这直接来自Java Docs

此类及其迭代器实现了 Collection 和 Iterator 接口的所有可选方法。方法 iterator() 中提供的 Iterator 不能保证以任何特定顺序遍历优先级队列的元素。如果您需要有序遍历,请考虑使用 Arrays.sort(pq.toArray())。

所以基本上,我的 PriorityQueue 工作正常,但是使用它自己的内置 toString() 方法将它打印到屏幕上导致我看到这个异常在运行,并且想知道是否有人可以解释为什么它是迭代器提供(并使用内部)不按自然顺序遍历 PriorityQueue?

4

5 回答 5

36

因为底层数据结构不支持它。二叉堆只是部分有序的,最小的元素在根。当您删除它时,堆会重新排序,以便下一个最小的元素位于根。没有有效的有序遍历算法,因此 Java 中没有提供。

于 2010-02-17T00:20:49.797 回答
4

PriorityQueues 是使用二叉堆实现的。 堆不是排序结构,它是部分排序的。每个元素都有一个与之关联的“优先级”。使用堆来实现优先级队列,它将始终在堆的根节点中拥有最高优先级的元素。因此在优先级队列中,优先级高的元素先于低优先级的元素提供服务。如果两个元素具有相同的优先级,则根据它们在队列中的顺序提供服务。每次移除元素后更新堆以保持堆属性

于 2017-09-28T07:39:45.403 回答
1

乍一看,它可能是按照数据的存储顺序遍历数据。为了最大限度地减少在队列中插入项目的时间,它通常不会按排序顺序存储所有项目。

于 2010-02-17T00:22:25.410 回答
0

好吧,正如 Javadoc 所说,这就是它的实现方式。优先级队列可能使用二进制堆作为底层数据结构。当您删除项目时,堆会重新排序以保留堆属性。

其次,绑定特定的实现(强制排序)是不明智的。使用当前的实现,您可以自由地以任何顺序遍历它并使用任何实现。

于 2010-02-17T00:23:52.023 回答
0

二进制堆是实现优先级队列的一种有效方式。关于堆的顺序的唯一保证是顶部的项目具有最高优先级(根据某些顺序,它可能是“最大”或“最小”)。堆是具有以下属性的二叉树: 形状属性:树从上到下从左到右填充顺序属性:任何节点上的元素都大于其两个子节点(如果最小则具有最高优先级则更小)。当迭代器访问所有元素时,它可能以级别顺序遍历的方式进行,即它在进入下一个级别之前依次访问每个级别中的每个节点。由于唯一保证节点的优先级高于其子节点的顺序,因此每个级别中的节点将没有特定的顺序。

于 2010-02-17T00:36:37.560 回答