我有地图
我期待像PriorityQueue这样的构造函数pq=new PriorityQueue(freqMap. keySet(),比较器);但是没有这样的构造函数。虽然我可以使用比较器构造它,然后使用addAll添加keySet元素但那会在内部逐个添加元素。以防我想用比较器作为值从键集中构建一个max堆。我不确定我该怎么做。
我的想法:
一种方法可能是,我创建一个自定义类并包装这些整数,并使该类实现一个可比较的接口。然后当我将该集合作为参数传递给priorityQueue构造函数时,它应该在O(n)时间内构造优先级队列。
而如果我使用addAll方法,那么可能需要O(n log n)时间。我不确定我的推理是否正确。仅仅使用一个实现可比较的包装类来实现这个微小的目的似乎有点复杂。可比将根据值进行比较,因此具有最高值的键应该在顶部。
在O(n)
时间构造优先级队列
您可以在线性时间O(n)内构造新的PriorityQueue
的唯一情况是您已经有另一个PriorityQueue
。
在这种情况下,拷贝构造函数将在内部调用方法initFromPriorityQueue()
,该方法将创建给定PriorityQueue
的底层数组的副本,并将此副本分配给此(新创建的)队列的底层数组。元素的复制将花费O(n)。
但是,当您的集合不是PriorityQueue
时,无法确保元素按要求排序。这意味着您需要一个接一个地将它们排队,没有解决方法。对于每个元素,它的成本为O(log n)。并且整体时间复杂度将是线性对数O(n log n)。
以下是关于操作时间复杂度的留档引用:
执行说明:
此实现为入队和出队方法(offer
、轮询
、删除()
和添加
)提供O(log(n))
时间;
由于二进制堆(PriorityQueue
是二进制堆数据结构的实现)在插入新元素时的最坏情况时间复杂度为O(log n),因此插入n
将在线性对数时间内运行。
关于addAll()
背后的机制,与许多其他集合一样,它委托给方法add()
,该方法具有对数最坏情况时间复杂度(参见上面引用的实现说明)。
注
>
上面提供的所有信息都与JDK中的PriorityQueue
类相关,该类实现为二进制堆(不要将该类与优先级队列数据结构混淆)。
实现Heap数据结构的方法有很多。其中一些方法,如Fibonacci Heap,已经分摊了插入的时间复杂度O(1),这允许在线性时间O(n)内用n
元素填充它们。在这样的实现中,将来会包含在JDK中,那么几乎可以肯定它不会取代当前的PriorityQueue
实现,而是作为一个新类引入(这就是Java从早期开始开发的方式:新事物来了,几乎没有什么消失)。