Java 使用hashmap实现优先级队列

Java 使用hashmap实现优先级队列,java,hashmap,priority-queue,Java,Hashmap,Priority Queue,这可能是一个非常幼稚的问题,也可能毫无意义。但我对优先级队列的实现感到困惑。 为什么我们不能使用键为优先级、值为具有该优先级的数据的hashmap。 我缺少一些基本的东西。 例如: 如果A的优先级为1,B为3,c为4 我们可以简单地将1、3、4分别保留为密钥,将A、B、C分别保留为hashmap的值,以实现优先级队列。 请清除我的逻辑当您尝试遍历HashMap时,您将得到一个奇怪的顺序HashMaps(或与此相关的任何映射)没有保证的遍历顺序,因此您将无法以有效的方式“排序”队列 当然,您可以查

这可能是一个非常幼稚的问题,也可能毫无意义。但我对优先级队列的实现感到困惑。 为什么我们不能使用键为优先级、值为具有该优先级的数据的hashmap。 我缺少一些基本的东西。 例如: 如果A的优先级为1,B为3,c为4 我们可以简单地将1、3、4分别保留为密钥,将A、B、C分别保留为hashmap的值,以实现优先级队列。
请清除我的逻辑

当您尝试遍历
HashMap
时,您将得到一个奇怪的顺序
HashMap
s(或与此相关的任何映射)没有保证的遍历顺序,因此您将无法以有效的方式“排序”队列


当然,您可以查询所有键,对该列表进行排序,并按顺序获取值,但与其他选项相比,这是非常低效的(在不做额外工作的情况下,键的长度已经达到O(n^2)

当您尝试迭代
HashMap
时,您将得到一个奇怪的顺序
HashMap
s(或与此相关的任何映射)没有保证的遍历顺序,因此您将无法以有效的方式“排序”队列


当然,您可以查询所有键,对该列表进行排序,并按顺序获取值,但与其他选项相比,这是非常低效的(在不做额外工作的情况下,键的长度已经达到O(n^2)

长话短说,这都归结为
HashMap
没有排序,因此,您最终需要某种外部机制来确定队列中的“下一步”是什么

例如,假设您输入了条目

[1, "A"]
[3, "B"]
[4, "C"]
如果您只有一个
HashMap
,那么没有可靠的方法可以确定
1
是迭代每个键的“第一个”,因为在内部键可能是:

[1, "A"]
[3, "B"]
[4, "C"]

等等

从:

此类不保证地图的顺序;特别是,它不能保证订单在一段时间内保持不变

因此,使用
HashMap
确实没有意义,因为无论如何,您必须做的额外工作最终会使
HashMap
的效率低于堆


现在,如果您真的想使用
HashMap
,您可以:

  • 抓取
    入口集
    ,按键排序,然后获取第一个值。如果这是您唯一需要获取第一个值的时间,那么这是可以的,但这种情况很少发生。一旦更改映射并需要再次执行,效率就会比常规堆差

  • 使用一些外部机制,例如
    ArrayList
    或其他东西来跟踪键,也许可以将其作为插入值的一部分进行排序。此时,我们不妨跳过
    HashMap
    并“正常”实现堆,因为除此之外,您基本上也在做同样的事情,但在
    ArrayList
    HashMap
    之间分割数据会增加复杂性


因此,最终,额外的工作并不值得。

长话短说,归根结底,这都是因为
HashMap
没有排序,因此您最终需要某种外部机制来确定队列中的“下一步”是什么

例如,假设您输入了条目

[1, "A"]
[3, "B"]
[4, "C"]
如果您只有一个
HashMap
,那么没有可靠的方法可以确定
1
是迭代每个键的“第一个”,因为在内部键可能是:

[1, "A"]
[3, "B"]
[4, "C"]

等等

从:

此类不保证地图的顺序;特别是,它不能保证订单在一段时间内保持不变

因此,使用
HashMap
确实没有意义,因为无论如何,您必须做的额外工作最终会使
HashMap
的效率低于堆


现在,如果您真的想使用
HashMap
,您可以:

  • 抓取
    入口集
    ,按键排序,然后获取第一个值。如果这是您唯一需要获取第一个值的时间,那么这是可以的,但这种情况很少发生。一旦更改映射并需要再次执行,效率就会比常规堆差

  • 使用一些外部机制,例如
    ArrayList
    或其他东西来跟踪键,也许可以将其作为插入值的一部分进行排序。此时,我们不妨跳过
    HashMap
    并“正常”实现堆,因为除此之外,您基本上也在做同样的事情,但在
    ArrayList
    HashMap
    之间分割数据会增加复杂性


因此,最终,额外的工作并不值得。

该实现的问题在于,它没有利用HashMap功能轻松访问给定密钥的任何元素。因为您正在创建一个队列,所以以后就不会有优先级1、3、4,只需要找到映射的最高优先级,必须完全迭代它才能找到

映射的工作原理是这样的:它创建了一个在所有位置都有空值的巨大数组(非常大)。然后,它使用一个公式获取键,通常是一个字符串或字符串表示形式,并将其转换为一个数字。一个简单的方法是对每个字母的字符代码求和,尽管这对映射来说是一个错误的选择,但您可以稍后查找原因。然后,它用数组的模(余数)大小(例如,Java中的n%大小)来限制该数字,使其成为数组中的有效位置,然后将元素放在那里。这样,进行密集搜索非常容易,因为您不需要搜索,您确切地知道每个元素的位置

因此,使用映射实现队列将非常占用内存,而没有HashMap搜索的明显优势。进一步的