如何减少 C++ 优先级队列的值?

Posted

技术标签:

【中文标题】如何减少 C++ 优先级队列的值?【英文标题】:How to reduce the value of C++ priority queue? 【发布时间】:2021-02-08 12:03:11 【问题描述】:

考虑我有一个顶部有最小值的min priority queue,我希望减少顶部的值,以便仍然保持队列的属性并且时间复杂度为O(1)。该怎么做?

我在这里看到了问题how to change the value of std::priority_queue top()?

哪里取值,修改再推回去,基本上是O(logN)的复杂度,不知道能不能利用减值的属性,这样就不需要再次推回价值?

【问题讨论】:

这在什么方面不是那个的复制品? 如果有O(1) 方法可以做到这一点,那么应该在您链接的问题上发布这样的答案。我不会以骗子的身份结束,因为这个问题中可能还有一个方面尚未解释。为什么您链接的问答没有回答您的问题? 从复杂性角度讲,由于优先级队列不是一个简单的数据结构,即使可以更改优先级值,也需要O(logN) 重新平衡它。所以无法摆脱 O(logN) 的复杂性,只是使用 pop&push 你需要重新平衡队列两次(这不会改变渐近复杂性) 你是在说std::priority_queue怎么办?如果优先级队列是自己做的,没问题。 您可以尝试使用最小堆,并直接修改底层向量的第一个元素。不确定它是否完全安全。 【参考方案1】:

标准优先级队列不支持更改键。

您正在寻找的是类似于另一个名为Indexed Priority Queue 的数据结构,通常被 Dijkstra 算法使用。

索引优先队列在其 API 中支持另外 2 种方法:increaseKeydecreaseKey 允许修改密钥本身。

STL 没有定义索引优先级队列。您可能需要自己实现一个或寻找一些第三方实现。

【讨论】:

【参考方案2】:

我对这个问题的看法与其他人不同。基于这个问题,

我有一个最小优先级队列,顶部的值最小,我希望减少顶部的值,这样队列的属性仍然是维护时间复杂度为 O(1)。

使用std::priority_queue,你不能。我们可以尝试像const_cast<int &>(pq.top()) = lesser_value_than_top 这样的黑客攻击。它可以在某些实现中工作,但并不安全。

所以,我想建议用基于数组的堆构建你自己的 PQ,你可以在没有 log(N) 工作的情况下更改顶部的值,只要它的值等于或小于当前顶部.

【讨论】:

嗨,谢谢。这正是我的意思。减少顶部值,这样就不需要重新堆积队列。

以上是关于如何减少 C++ 优先级队列的值?的主要内容,如果未能解决你的问题,请参考以下文章

C++ 标准模板库优先级队列抛出异常并显示消息“无效堆”

当对头元素使用引用时,C++ 优先级队列的行为很奇怪

如何在 C++ 中正确使用优先级队列

增加和减少优先级队列的模板函数

如何使用优先队列根据键值对的值进行排序

初始化并插入优先级队列 (C++)