[英]std::priority_queue with iterators to elements of std::map - invalid heap
我没有粘贴所有代码,因为它可能太复杂了。 我会先尝试写下我的问题。
我尝试实现一些算法。 我需要容器(键值)与键访问(如std::map
),我需要快速访问具有最大值的get(和remove)元素。
所以我使用std::map<key, value> myMap
,我有std::priority_queue<std::map<key, value>::iterator> myQueue
。
typedef std::map<cv::Point, double>::iterator mapIter;
class mycomparison
{
public:
bool operator() (mapIter lhs, mapIter rhs) const
{
return lhs->second > rhs->second; // (*)
}
};
std::priority_queue<mapIter, std::vector<mapIter>, mycomparison> myQueue;
// I fill `myQueue` with iterator to every element of `myMap` ...
while (!myQueue.empty())
{
mapIter iter = myQueue.top();
// ...
// ...
if (myMap[key1] > myMap[iter->first] + someValue)
myMap[key1] = myMap[iter->first] + someValue; // (**)
myQueue.pop();
}
我有调试它的问题。 我在myQueue.pop()
期间myQueue.pop()
- Invalid heap
。 当我用(**)评论时。 没有错误。
怎么了? 这是不安全的操作吗?
或者错误是另一条线?
comparision
(*)怎么样? 当我返回时return lhs->second > rhs->second;
一切都很好看。 但我需要>操作。
我无法理解为什么会有错误。 我花了很多时间。 任何的想法?
我认为这是我这个问题的重要代码......
问题很简单,地图中值的赋值会导致堆条件被违反:由于您在优先级队列中存储的元素不是值,而只是引用值,因此更改元素可能会破坏必要的条件! 仅仅因为更改元素的键并不意味着优先级队列将重新排列优先级队列的结构。
您似乎正在尝试实现Dijkstra的最短路径算法,该算法需要在检测到已到达节点的路径较短时更新节点的密钥。 要处理这些更新,您需要以某种方式引用优先级队列中需要更新的节点。 通常使用Fibonacci-heap来有效地实现这种算法,这也具有基于节点而不是基于数组的优点:Fibonacci-heap中的元素保留在内存中,这样可以很容易地保留对节点的引用。调整。
可以使用d-heap实现类似的逻辑,但std::priority_queue<T>
不提供此功能。 使用具有固定节点位置的d堆的方法是存储辅助数组,该数组具有指向d堆中的节点的指针,其提供用于更新的密钥。 当移动d堆中的元素时,辅助数组中的相应指针也会更新。 这些更新大大减慢了处理速度,这是它们在不需要时不会完成的原因,例如,对于可用于堆排序的std::priority_queue<T>
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.