我什么时候应该使用TreeMap 而不是 PriorityQueue?反之亦然?

引子

之前周赛(第 390 场周赛记录-快手)时遇到一题(题干描述见下图,实现代码见周赛记录),需要保持容器元素的动态有序(即随着插入删除操作后列表始终是有序的)。尝试过很多数据结构或方案,如列表存储然后手动调用Arrays.sort()进行排序、使用优先队列实现大/小根堆的方式,但无一例外全部超时😡...

最后用 TreeMap 数据结构方才成功通过✅。因此引发了对一个问题的思考:TreeMap 和 PriorityQueue虽然都是动态保持容器元素有序的数据结构,可以获取最大值/最小值,但是差异在哪呢,什么时候使用其中一个会比使用另外一个更有优势呢?🤔

正文

去网上一搜,发现并不是只有我有这个疑问,以下是关于 StackOverFlow 的高赞问答贴:

When should I use a TreeMap over a PriorityQueue and vice versa?

Seems they both let you retrieve the minimum, which is what I need for Prim's algorithm, and force me to remove and reinsert a key to update its value. Is there any advantage of using one over the other, not just for this example, but generally speaking?

总结高赞回复贴内容如下,TreeMap 和 PriorityQueue 区别如下,何时使用哪一个可以据此进行分析:

1️⃣ PriorityQueue 允许重复(即具有相同的优先级),而 TreeMap 不允许。
2️⃣ PriorityQueue 的复杂度是 O(n)(当它增加其大小时),而 TreeMap 的复杂度是 O(logn)(因为它基于红黑树)
3️⃣ PriorityQueue 是基于 Array 的,而 TreeMap 中的节点是相互连接的,因此 PriorityQueue 的 contains 方法将花费 O(n) 时间,而 TreeMap 将花费 O(logn) 时间。

针对引子中的题目来说,在基于普通堆的 PriorityQueue(如 Oracle)中,remove(Object) 和 contains(Object) 是线性 O(N),但对于 TreeSet/Map 来说是 O(log(N))。因此,如果存在大量元素并执行大量删除(对象)或包含(对象)的情况,那么 TreeSet/Map 可能会更快。

✨ 由于 PriorityQueue 在维护数据总序方面能力较弱,但在一些特殊情况下具有优势。 如果要跟踪 N 数组中最大的 M 个元素,时间复杂度将是 O(NLogM),空间复杂度将是 O(M)。 但如果在TreeMap中执行,则时间复杂度为 O(NlogN),空间复杂度为 O(N)。 这是非常基本的,但在某些情况下我们必须使用优先级队列,例如 M 只是一个像 10 这样的常数。总的来说,TreeMap 维护所有元素的有序(直观上来说,构建起来是需要时间的)。而PriorityQueue 仅保证最小值或最大值。 它获取最值开销相对较小,但功能更弱。

posted @ 2024-03-25 16:08  无发可说  阅读(96)  评论(0编辑  收藏  举报