[英]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.