C++ 如何用哈希表在最小堆上实现O(1)删除

C++ 如何用哈希表在最小堆上实现O(1)删除,c++,algorithm,C++,Algorithm,请在某处阅读以下语句: 可以使用附加的哈希表在中快速删除 最小堆 问题>如何组合优先级队列和无序映射,以便实现上述想法 #include <queue> #include <unordered_map> #include <iostream> #include <list> using namespace std; struct Age { Age(int age) : m_age(age) {} int m_age; }; //

请在某处阅读以下语句:


可以使用附加的哈希表在中快速删除 最小堆

问题>如何组合
优先级队列
无序映射
,以便实现上述想法

#include <queue>
#include <unordered_map>
#include <iostream>
#include <list>
using namespace std;

struct Age
{
  Age(int age) : m_age(age) {}
  int m_age;  
};

// Hash function for Age
class HashAge {
  public:
   const size_t operator()(const Age &a) const {
     return hash<int>()(a.m_age);
   }
};

struct AgeGreater
{
  bool operator()(const Age& lhs, const Age& rhs) const {
    return lhs.m_age < rhs.m_age;
  }
};

int main()
{
  priority_queue<Age, list<Age>, AgeGreater> min_heap;          // doesn't work
  //priority_queue<Age, vector<Age>, AgeGreater> min_heap;

  // Is this the right way to do it?
  unordered_map<Age, list<Age>::iterator, HashAge > hashTable;     
}
#包括
#包括
#包括
#包括
使用名称空间std;
结构年龄
{
年龄(整数年龄):m_年龄(年龄){}
int m_年龄;
};
//年龄哈希函数
类哈希{
公众:
常量大小\u t运算符()(常量年龄和a)常量{
返回hash()(a.m_age);
}
};
结构年龄更大
{
布尔运算符(){
返回lhs.m_年龄优先级队列)

您不能使用提供的
优先级队列
数据结构执行此操作:

在优先级队列中,您不知道元素存储在哪里,因此很难在固定时间内删除它们,因为您找不到元素。但是,如果您维护一个哈希表,其中每个元素在优先级队列中的位置都存储在哈希表中,那么您可以快速找到并删除一个项,尽管我希望是log(N)在最坏的情况下是时间,而不是常数时间。(如果你得到摊销常数时间,我不会马上想起。)

要做到这一点,通常需要滚动自己的数据结构,因为每次在优先级队列中移动项目时,都必须更新哈希表

我这里有一些示例代码可以实现这一点:

它基于较旧的编码风格,但它可以做到这一点

举例说明:

/**
 * Moves a node up the heap. Returns true if the node was moved, false otherwise.
 */
template<typename state, typename CmpKey, class dataStructure>
bool AStarOpenClosed<state, CmpKey, dataStructure>::HeapifyUp(unsigned int index)
{
        if (index == 0) return false;
        int parent = (index-1)/2;
        CmpKey compare;

        if (compare(elements[theHeap[parent]], elements[theHeap[index]]))
        {
                // Perform normal heap operations
                unsigned int tmp = theHeap[parent];
                theHeap[parent] = theHeap[index];
                theHeap[index] = tmp;
                // Update the element location in the hash table
                elements[theHeap[parent]].openLocation = parent;
                elements[theHeap[index]].openLocation = index;
                HeapifyUp(parent);
                return true;
        }
        return false;
}
/**
*将节点向上移动堆。如果节点已移动,则返回true,否则返回false。
*/
模板
bool astarropenclosed::HeapifyUp(无符号整数索引)
{
如果(索引==0)返回false;
int parent=(索引-1)/2;
CmpKey比较;
if(比较(元素[theHeap[parent]],元素[theHeap[index]]))
{
//执行正常的堆操作
unsigned int tmp=theHeap[parent];
heap[parent]=heap[index];
heap[index]=tmp;
//更新哈希表中的元素位置
元素[theHeap[parent]]。openLocation=parent;
元素[theHeap[index]]。openLocation=index;
HeapifyUp(父母);
返回true;
}
返回false;
}

if
语句中,我们对堆执行正常的heapify操作,然后更新哈希表中的位置(
openLocation
)指向优先级队列中的当前位置。

我想我想知道为什么要使用优先级队列来实现最小堆,因为我习惯了使用优先级队列实现最小堆。您在哪里读过这篇文章?“可以使用附加哈希表在最小堆中快速删除。”虽然这可能是真的,也可能不是真的,但这句话并没有具体提到
priority\u queue
unordered\u map
,我严重怀疑它们能否有效地结合使用,更不用说评论中讨论的方式了。你是对的,这本书也没有提到priority\u queue或unordered\u map。在这里,我想不希望在基于该思想的C++中实现这个思想。你可以用哈希表来获得固定的常数,但是优先级队列不能比<代码> log n<代码>做得更好,而不必破坏优先级队列的实现……并且可能破坏其他操作的性能(如:插入)。..…对于大多数声明插入(或删除)为O(1)的变体,它附带了一个巨大的常数因子,使得实际性能比简单的二进制堆更差。
/**
 * Moves a node up the heap. Returns true if the node was moved, false otherwise.
 */
template<typename state, typename CmpKey, class dataStructure>
bool AStarOpenClosed<state, CmpKey, dataStructure>::HeapifyUp(unsigned int index)
{
        if (index == 0) return false;
        int parent = (index-1)/2;
        CmpKey compare;

        if (compare(elements[theHeap[parent]], elements[theHeap[index]]))
        {
                // Perform normal heap operations
                unsigned int tmp = theHeap[parent];
                theHeap[parent] = theHeap[index];
                theHeap[index] = tmp;
                // Update the element location in the hash table
                elements[theHeap[parent]].openLocation = parent;
                elements[theHeap[index]].openLocation = index;
                HeapifyUp(parent);
                return true;
        }
        return false;
}