实现优先级队列和堆
implementing priority queues and heaps
我正在尝试根据 "Introduction to Algorithms, Third Edition" 中的描述使用二进制最小堆实现最小优先级队列并有几个问题。
书上说我们经常需要在每个堆元素中存储一个应用对象的句柄(指针或整数),还需要在每个应用对象中存储一个堆元素的句柄(数组索引) .
1) 堆实现通常看起来像这样吗?
template <class KeyType, class ObjectType>
struct HeapElement
{
KeyType key;
ObjectType* pObject;
};
template <class KeyType, class ObjectType>
class MinHeap
{
// ...
private:
std::vector< HeapElement<KeyType, ObjectType> > data;
};
然后 ObjectType class 也会存储 heapIndex:
class Foo
{
// ...
int heapIndex;
};
2) 最小优先级队列和二进制最小堆通常作为单个实现 class 还是最小优先级队列通常作为其自身实现 class 与私有堆 class 成员?
class MinPriorityQueue
{
// ...
private:
MinHeap minHeap;
};
我问的原因是因为如果您查看 ExtractMin()
之类的实现,它需要您操作堆数据:
int min = data[0]; // data: private heap data member
heapSize--; // heapSize: private heap data member
MinHeapify(0); // MinHeapify: private heap member function
所以也许最小优先级队列 class 应该充当包装器 class?
T MinPriorityQueue::ExtractMin()
{
return minHeap.ExtractMin();
}
在这种情况下,二进制最小堆 class 可能会实现 Min()
、ExtractMin()
、DecreaseKey()
和 Insert()
并包含两者的功能二进制最小堆和最小优先级队列。那么根本不需要 MinPriorityQueue class。
问题的范围是实施 heaps/priority 面试队列。对此有什么想法吗?
1) 通常你不想仅仅因为你想把它们堆成一堆就必须修改你的值类型。你会让你的堆像这样:
template <class KeyType, class ObjectType>
struct HeapElement
{
KeyType key;
size_t heapIndex;
ObjectType* pObject;
};
template <class KeyType, class ObjectType>
class MinHeap
{
// ...
private:
//this is just to allocate the data. Elements in here don't move
std::vector< HeapElement<KeyType, ObjectType> > data;
//this is the heap. Elements are indexes into data vector
std::vector<size_t> heapArray;
};
然后,在整个 Dijkstra 算法的实现过程中,您使用数据向量中的索引来引用对象,并且您可以使用 data[itemIndex].heapIndex
.
获取每个项目的堆索引
但请在此处查看我的回答: ...我通常在不使用 decrease_key 操作的情况下 实施 Dijkstra 算法。
2) 我真的看不出有什么理由要创建一个与优先级队列实现分开的堆 class。我实际上会调用 class 你需要一个 "Heap",但不是优先级队列,因为优先级队列接口通常不期望键与对象分开。
您应该在矢量上使用std::make_heap
、std::push_heap
和std::pop_heap
。
我正在尝试根据 "Introduction to Algorithms, Third Edition" 中的描述使用二进制最小堆实现最小优先级队列并有几个问题。
书上说我们经常需要在每个堆元素中存储一个应用对象的句柄(指针或整数),还需要在每个应用对象中存储一个堆元素的句柄(数组索引) .
1) 堆实现通常看起来像这样吗?
template <class KeyType, class ObjectType>
struct HeapElement
{
KeyType key;
ObjectType* pObject;
};
template <class KeyType, class ObjectType>
class MinHeap
{
// ...
private:
std::vector< HeapElement<KeyType, ObjectType> > data;
};
然后 ObjectType class 也会存储 heapIndex:
class Foo
{
// ...
int heapIndex;
};
2) 最小优先级队列和二进制最小堆通常作为单个实现 class 还是最小优先级队列通常作为其自身实现 class 与私有堆 class 成员?
class MinPriorityQueue
{
// ...
private:
MinHeap minHeap;
};
我问的原因是因为如果您查看 ExtractMin()
之类的实现,它需要您操作堆数据:
int min = data[0]; // data: private heap data member
heapSize--; // heapSize: private heap data member
MinHeapify(0); // MinHeapify: private heap member function
所以也许最小优先级队列 class 应该充当包装器 class?
T MinPriorityQueue::ExtractMin()
{
return minHeap.ExtractMin();
}
在这种情况下,二进制最小堆 class 可能会实现 Min()
、ExtractMin()
、DecreaseKey()
和 Insert()
并包含两者的功能二进制最小堆和最小优先级队列。那么根本不需要 MinPriorityQueue class。
问题的范围是实施 heaps/priority 面试队列。对此有什么想法吗?
1) 通常你不想仅仅因为你想把它们堆成一堆就必须修改你的值类型。你会让你的堆像这样:
template <class KeyType, class ObjectType>
struct HeapElement
{
KeyType key;
size_t heapIndex;
ObjectType* pObject;
};
template <class KeyType, class ObjectType>
class MinHeap
{
// ...
private:
//this is just to allocate the data. Elements in here don't move
std::vector< HeapElement<KeyType, ObjectType> > data;
//this is the heap. Elements are indexes into data vector
std::vector<size_t> heapArray;
};
然后,在整个 Dijkstra 算法的实现过程中,您使用数据向量中的索引来引用对象,并且您可以使用 data[itemIndex].heapIndex
.
但请在此处查看我的回答:
2) 我真的看不出有什么理由要创建一个与优先级队列实现分开的堆 class。我实际上会调用 class 你需要一个 "Heap",但不是优先级队列,因为优先级队列接口通常不期望键与对象分开。
您应该在矢量上使用std::make_heap
、std::push_heap
和std::pop_heap
。