微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

存在堆时,优先级队列的目的是什么?

如何解决存在堆时,优先级队列的目的是什么?

我知道优先级队列倾向于使用堆,但是当优先级队列看起来与堆基本相同时,优先级队列的意义是什么?我最初以为所有优先级队列都使用哈希映射来跟踪堆中所有对象的位置,从而使查找和更新/删除该对象变得更加容易。但是,我使用了Java的优先级队列,您必须手动对其进行迭代以更新或删除不在根目录下的对象。有一个优先级队列似乎只是一个堆,没有其他特别之处,这似乎很奇怪。

解决方法

在这里类推可能有助于推理:

List是动态数组,而PriorityQueue是二进制堆。

也就是说,列表的抽象概念(一系列从零位置开始的事物序列,可以插入和删除项目)是一个很好的高级概念,而动态数组(具有容量的数组如果需要额外的空间,则将其大小增加一倍或1.5倍)是实现列表的一种可能方式。如果您使用的是列表,则可以考虑“哦,这是一个序列,我可以放东西”,而不必担心该序列的实际表示方式。另一方面,使用动态数组需要您跟踪哪些数组元素有效以及哪些元素未被实际使用,您需要在没有更多空间时手动转移内容,并仔细考虑您的增长策略,等等。这里的区别是您正在查看事物的级别。如果只需要“序列”,请考虑“列表”。如果您需要从头开始构建表示序列的类型,请考虑“动态数组”。

基本上,这就是优先级队列与二进制堆的关系。优先级队列抽象地表示“我可以放入东西,它们会按排序顺序返回。”二进制堆是实现优先级队列的一种特定的可能方式。当使用抽象优先级队列时,您可以将思想纯粹集中在“我想添加什么元素?”之类的问题上。和“我如何对它们进行排名?”在使用二进制堆时,您必须考虑“我使用单索引还是零索引?”这样的事情。以及“用于标识索引k处的节点的子代的公式是什么?”如果您所需要的只是将事物放入袋子中并按已排序顺序取出的能力,则可以使用优先级队列而不必担心其工作原理。如果需要从头开始构建一个,可以使用二进制堆。

回到列表与动态数组的类比:可以使用许多类型来表示列表。动态数组是其中之一,但是您也可以使用循环缓冲区(如果在末端添加或删除,则很好)或链接列表(如果项目在列表之间移动,则很好)。同样,有许多方法可以实现优先级队列。二进制堆是一种选择,但也有配对堆,二项式堆等。保持相关抽象的重点-我只想要一系列事物,我只想要一种以排序顺序检索事物的方式-意味着您不需要当您关心的是要执行的操作时,就需要尽可能多地担心事情是如何工作的。

,

个人观点,您是对的,Java的PriorityQueue是堆。 Java作为一种高级编程语言,它合理地提供了所有通用和标准算法实现,大多数时候我们专注于业务逻辑开发以及如何更快地完成工作。因此,我们不想花太多时间从头开始构建优先级队列,除了自己做这很麻烦而且容易出错。 如果要同时更新或删除对象,并且不想手动对其进行迭代,则可以执行以下操作:

Object updatedObject;
priorityQueue.add(priorityQueue.remove(updatedObject));

尽管频繁进行更新时效率不够高,但是还有一种名为Fibonacci heap的替代算法可以更好地完成工作:

,

有一个优先级队列似乎从字面上看只是一个堆,没有其他特别之处,这似乎很奇怪。

为什么?

名称PriorityQueue的最大承诺就是能够按照优先级将项目放入一端并从另一端取出它们。这基本上也是堆的定义,这就是为什么堆使理想的数据结构实现优先级队列的原因。

因此,从本质上讲,Java Collections Framework设计人员实现了一个堆。他们只是将其称为Heap,而不是将其称为PriorityQueue。故事结局。歌曲歌词中写道:“谁还能要求更多?”

,

Java的优先级队列可以是最小堆或最大堆,根据您的构造方式,它将始终为您提供最小/最大值。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。