简体   繁体   English

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

[英]Implement decreaseKey in STL Priority Queue C++

I'm trying to implement Prim's Algorithm and for that I need to have a decreaseKey method for a priority queue (to update the key value in a priority queue). 我正在尝试实现Prim的算法,为此我需要为优先级队列使用reduceKey方法(以更新优先级队列中的键值)。 Can I implement this in the STL Priority Queue? 我可以在STL优先级队列中实现吗?

If it helps, this is the algorithm I'm following: 如果它有帮助,这是我遵循的算法:

  • for each vertex u in graph G 对于图G中的每个顶点u
    • set key of u to INFINITY 将你的关键设置为INFINITY
    • set parent of u to NIL 将u的父级设置为NIL
  • set key of source vertex to 0 将源顶点的键设置为0
  • en-queue to priority queue Q all vertices in graph with keys as above en-queue to priority queue Q图中的所有顶点,如上所示
  • while Q is not empty 而Q不是空的
    • pop vertex u with lowest key in Q 在Q中使用最低键弹出顶点u
    • for each adjacent vertex v of u do 对于你做的每个相邻顶点v
      • if (v is still in Q) and (key(u) + weight-function(u, v) < key(v)) then if(v仍在Q中)和(key(u)+ weight-function(u,v)<key(v))然后
        • set u to be parent of v 设定你是v的父母
        • update v's key to equal key(u) + weight-function(u, v) // This part is giving me problems as I don't know how implement decreaseKey in priority queue 更新v键等于键(u)+权重函数(u,v) //这部分给我带来问题,因为我不知道如何在优先级队列中实现reduceKey

I do not think you can implement it in STL container. 我不认为你可以在STL容器中实现它。 Remember you can always write your own heap(priority queue) based on vector, but there is a work around: 记住你总是可以根据vector编写自己的堆(优先级队列),但有一个解决方法:

Keep array of distances you have, lets say d . 让你有距离的阵列,可以说d In you priority queue you put pairs of distances and index of vertex of this distance. 在优先级队列中,您可以放置​​成对的距离和此距离的顶点索引。 When you need to delete some value from queue, do not delete it, just update your value in d array and put new pair into queue. 当你需要从队列中删除一些值时,不要删除它,只需更新d数组中的值并将新对放入队列。

Every time you take new value from queue, check if distance in pair is actually that good, as in your array d . 每次从队列中获取新值时,请检查对中的距离是否实际上是好的,就像在数组d If not ignore it. 如果不理睬它。

Time is same O(MlogM). 时间相同O(MlogM)。 Memory is O(MlogM), where M is number of edges. 内存为O(MlogM),其中M是边数。

There is another approach: use RB-Tree, it can insert and delete keys in O(logN) and get minimum as well. 还有另一种方法:使用RB-Tree,它可以在O(logN)中插入和删除键,并且也可以获得最小值。 You can find implementation in STL of RB-Tree in std::set container. 您可以在std::set容器中的RB-Tree的STL中找到实现。

But, although time complexity is same, RB-Tree works slower and has bigger hidden constant, so it might be slightly slower, appx. 但是,虽然时间复杂度相同,但RB-Tree工作速度较慢且隐藏常数较大,因此可能会稍微慢一些,即appx。 5 times slower. 慢5倍。 Depends on data, of course . 当然,取决于数据。

For the other approach : better than using a std::set. 对于另一种方法:比使用std :: set更好。 You may use a btree::btree_set (or btree::safe_btree_set). 您可以使用btree :: btree_set(或btree :: safe_btree_set)。 This is an implementation identical to std::set made by google using B-Tree unlike stl which use RB-Tree. 这是一个与谷歌使用B-Tree制作的std :: set相同的实现,与使用RB-Tree的stl不同。 This much better than std::set and also O(logN). 这比std :: set和O(logN)要好得多。 check the performance comparison : http://code.google.com/p/cpp-btree/wiki/UsageInstructions And it has also a much lower memory footprint. 检查性能比较: http//code.google.com/p/cpp-btree/wiki/UsageInstructions它的内存占用量也要低得多。

I'm no expert, so hope this is not too dumb, but would a vector combined with lower_bound work very well? 我不是专家,所以希望这不是太愚蠢,但是一个矢量与low_bound相结合的工作会非常好吗?

If you use lower_bound to find the correct place to insert new values, your vector will always be sorted as you build it, no sorting required. 如果使用lower_bound来查找插入新值的正确位置,则在构建时将始终对向量进行排序,无需排序。 When your vector is sorted, isn't lower_bound a binary search with logarithmic class performance? 对矢量进行排序时,不是lower_bound是具有对数类性能的二进制搜索吗?

Since it is sorted, finding the min value (or max) is a snap. 由于它已排序,因此查找最小值(或最大值)非常简单。

To reduce key, you'd do a lower_bound search, delete, and do lower_bound again to insert the reduced key, which = 2 logarithmic class operations. 要减少密钥,您需要执行lower_bound搜索,删除和再次执行lower_bound以插入简化密钥,即2个对数类操作。 Still not bad. 还不错。

Alternatively, you could update the key and sort the vector. 或者,您可以更新密钥并对矢量进行排序。 I would guess with random access, that should still be in the logarithmic class, but don't know exactly what stl does there. 我猜测随机访问,应该仍然在对数类中,但不知道stl在那里做了什么。

With sorted vector, if you know the candidate key is less than the one that's in there, then maybe you could even just sort the part of the vector that has all the lesser values for even better performance. 使用排序向量,如果您知道候选键小于那里的候选键,那么您甚至可以只对具有所有较小值的向量部分进行排序以获得更好的性能。

Another consideration is I think sets/maps have quite a bit more memory overhead than vectors do? 另一个考虑因素是我认为集合/映射比向量具有更多的内存开销吗?

I think most sorting is limited to NLogN, so 2 LogN for re-inserting rather than sorting might be better for the reduce key operation. 我认为大多数排序仅限于NLogN,因此重新插入而不是排序的2 LogN对于reduce键操作可能更好。

The other thing is inserting in vector is not so hot, however on the whole, does the idea of vector w lower_bound seem worth considering? 另一件事是插入向量并不是那么热,但总的来说,vector w lower_bound的想法是否值得考虑?

thanks 谢谢

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM