在STL优先级队列C ++中实现decreaseKey

时间:2013-01-19 09:09:18

标签: c++ stl priority-queue prims-algorithm decrease-key

我正在尝试实现Prim算法,为此我需要为优先级队列设置一个reduceKey方法(以更新优先级队列中的键值)。我可以在STL优先级队列中实现吗?

如果有帮助,这就是我正在遵循的算法:

  • 表示图G中的每个顶点u
    • 将你的密钥设置为INFINITY
    • 将u的父级设为NIL
  • 将源顶点的键设置为0
  • 队列到优先级队列Q图中的所有顶点都带有上面的键
  • 而Q不为空
    • 使用Q
    • 中的最低键弹出顶点u
    • 对于你做的每个相邻顶点v
      • if(v仍在Q中)和(key(u)+ weight-function(u,v)< key(v))然后
        • 将你设为v
        • 的父母
        • 将v的密钥更新为等于密钥(u)+权重函数(u,v) //这部分给我带来问题,因为我不知道如何在优先级队列中实现reduceKey

4 个答案:

答案 0 :(得分:8)

我认为你不能在STL容器中实现它。请记住,您总是可以根据向量编写自己的堆(优先级队列),但有一个解决方法:

保持一定距离,让我们说d。在优先级队列中,您可以放置​​成对的距离和此距离的顶点索引。当你需要从队列中删除一些值时,不要删除它,只需更新d数组中的值并将新对放入队列。

每次从队列中获取新值时,请检查对中的距离是否实际上是好的,就像在数组d中一样。如果不理睬它。

时间与O(MlogM)相同。内存为O(MlogM),其中M是边数。

还有另一种方法:使用RB-Tree,它可以在O(logN)中插入和删除键,也可以获得最小值。您可以在std::set容器中的RB-Tree的STL中找到实现。

但是,虽然时间复杂度相同,但RB-Tree的工作速度较慢且隐藏常数较大,因此可能会稍微慢一点,appx。慢5倍。当然,取决于数据。

答案 1 :(得分:2)

对于另一种方法:比使用std :: set更好。 您可以使用btree :: btree_set(或btree :: safe_btree_set)。 这是一个与谷歌使用B-Tree制作的std :: set相同的实现,与使用RB-Tree的stl不同。这比std :: set和O(logN)要好得多。 检查性能比较: http://code.google.com/p/cpp-btree/wiki/UsageInstructions 它的内存占用量也要低得多。

答案 2 :(得分:0)

我不是专家,所以希望这不是太愚蠢,但是一个矢量与lower_bound结合起来会非常好吗?

如果使用lower_bound来查找插入新值的正确位置,则在构建时将始终对向量进行排序,无需排序。对矢量进行排序时,不是lower_bound是具有对数类性能的二进制搜索吗?

由于它已排序,因此快速找到最小值(或最大值)。

要减少密钥,您需要执行lower_bound搜索,删除和再次执行lower_bound以插入简化密钥,即= 2对数类操作。还不错。

或者,您可以更新密钥并对矢量进行排序。我猜测随机访问,应该仍然在对数类中,但不知道stl在那里做了什么。

使用排序向量,如果您知道候选键小于其中的候选键,那么您甚至可以对具有所有较小值的向量部分进行排序以获得更好的性能。

另一个考虑因素是我认为集合/映射比向量具有更多的内存开销吗?

答案 3 :(得分:0)

我认为大多数排序仅限于NLogN,因此重新插入而不是排序的2 LogN对于reduce键操作可能更好。

另一件事是插入向量并不是那么热,但总的来说,vector w lower_bound的想法是否值得考虑?

感谢