简体   繁体   English

std :: priority_queue与迭代器到std :: map的元素 - 无效堆

[英]std::priority_queue with iterators to elements of std::map - invalid heap

I haven't pasted all code because it could be too much complicated. 我没有粘贴所有代码,因为它可能太复杂了。 I'll try to write about my problem first. 我会先尝试写下我的问题。

I try to implement some algorithm. 我尝试实现一些算法。 I need container (key-value) with with access by key (like std::map ) and I need to fast access to get (and remove) element with maximum value. 我需要容器(键值)与键访问(如std::map ),我需要快速访问具有最大值的get(和remove)元素。

So I use std::map<key, value> myMap and I have std::priority_queue<std::map<key, value>::iterator> myQueue . 所以我使用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();
    }

I have problem with debugging it. 我有调试它的问题。 I have an error during myQueue.pop() - Invalid heap . 我在myQueue.pop()期间myQueue.pop() - Invalid heap When I commented line with (**). 当我用(**)评论时。 There is no error. 没有错误。

What is wrong? 怎么了? Is it unsafe operation? 这是不安全的操作吗?

Or maybe mistake is in another line? 或者错误是另一条线?

How about comparision (*)? comparision (*)怎么样? When I return return lhs->second > rhs->second; 当我返回时return lhs->second > rhs->second; Everything looks OK. 一切都很好看。 But I need > operation. 但我需要>操作。

I couldn't understand why there is an error. 我无法理解为什么会有错误。 I spent many hours. 我花了很多时间。 Any idea? 任何的想法?

I think it's all my important code for this question... 我认为这是我这个问题的重要代码......

The problem is simply that the assignment to the values in the map causes the heap condition to become violated: since the elements you are storing in the priority queue are not the values but only reference the values, changing the elements can break the necessary conditions! 问题很简单,地图中值的赋值会导致堆条件被违反:由于您在优先级队列中存储的元素不是值,而只是引用值,因此更改元素可能会破坏必要的条件! Just because you change the key of an element doesn't mean that the priority queue will rearrange the structure of the priority queue. 仅仅因为更改元素的键并不意味着优先级队列将重新排列优先级队列的结构。

It seems you are trying to implement Dijkstra's shortest path algorithm which requires updating the key of a node when it is detected that there is a shorter path to an already reached node. 您似乎正在尝试实现Dijkstra的最短路径算法,该算法需要在检测到已到达节点的路径较短时更新节点的密钥。 To deal with these updates you'll need to somehow reference the node in the in the priority queue which needs to be updated. 要处理这些更新,您需要以某种方式引用优先级队列中需要更新的节点。 Conventionally a Fibonacci-heap is used to implement this algorithms efficiently which also has the advantage that it is node based rather than array based: elements in a Fibonacci-heap stay put in memory making it easy to keep a reference to the node which can then be adjusted. 通常使用Fibonacci-heap来有效地实现这种算法,这也具有基于节点而不是基于数组的优点:F​​ibonacci-heap中的元素保留在内存中,这样可以很容易地保留对节点的引用。调整。

A similar logic can be implemented with a d-heap but std::priority_queue<T> doesn't provide this functionality. 可以使用d-heap实现类似的逻辑,但std::priority_queue<T>不提供此功能。 The approach to use a d-heap with fixed node positions is to store an auxiliary array with pointers to the nodes in the d-heap which provides the keys used for updates. 使用具有固定节点位置的d堆的方法是存储辅助数组,该数组具有指向d堆中的节点的指针,其提供用于更新的密钥。 When elements in the d-heap are moved the corresponding pointers in the auxiliary array are also updated. 当移动d堆中的元素时,辅助数组中的相应指针也会更新。 These updates slow down the processing substantially which is the reason they are not done when they are not needed, eg, for std::priority_queue<T> which can be used for heap-sort. 这些更新大大减慢了处理速度,这是它们在不需要时不会完成的原因,例如,对于可用于堆排序的std::priority_queue<T>

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

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