我正在尝试使用基于“算法简介,第三版”中的描述使用二进制最小堆来实现最小优先级队列,并且有几个问题。
本书说我们经常需要将句柄(指针或整数)存储到每个堆元素中的应用程序对象中,并且我们还需要将句柄(数组索引)存储到每个应用程序对象中的堆元素。 / p>
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类也会存储heapIndex:
class Foo
{
// ...
int heapIndex;
};
2)最小优先级队列和二进制最小堆通常是作为单个类实现还是最小优先级队列通常作为自己的类实现,具有私有堆类成员?
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
那么最小优先级队列类是否应该作为包装类?
T MinPriorityQueue::ExtractMin()
{
return minHeap.ExtractMin();
}
在这种情况下,二进制最小堆类可能会实现Min()
,ExtractMin()
,DecreaseKey()
和Insert()
,并包含二进制最小堆和最小值的功能优先队列。然后根本不需要MinPriorityQueue类。
问题的范围是为求职面试实施堆积/优先队列。有什么想法吗?
答案 0 :(得分:0)
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
获取每个项目的堆索引。
但请看我的回答:Prim's Algorithm: How to get index of key on which DECREASE_KEY operation is to be performed? ...我通常在没有 reduce_key操作的情况下实现Dijkstra的算法。
2)我真的没有理由建立一个与优先级队列实现分开的堆类。我实际上会称这个类需要一个“堆”,但不是优先级队列,因为优先级队列接口通常不希望密钥与对象分开。