0

I am trying to implement a min priority queue using a binary min heap based on the description from "Introduction to Algorithms, Third Edition" and have a couple of questions.

The book says that we often need to store a handle (pointer or integer) to the application object in each heap element and that we also need to store a handle (array index) to the heap element in each application object.

1) Would the heap implementation typically look something like this then?

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;
};

And then the ObjectType class would also store the heapIndex:

class Foo
{
 // ...
  int heapIndex;
};

2) Is the min priority queue and binary min heap typically implemented as a single class or is the min priority queue usually implemented as its own class with a private heap class member?

class MinPriorityQueue
{
  // ...
private:
  MinHeap minHeap;
};

The reason I ask is because if you look at the implementation for something like ExtractMin(), it requires that you manipulate the heap data:

int min = data[0]; // data: private heap data member
heapSize--; // heapSize: private heap data member
MinHeapify(0); // MinHeapify: private heap member function

So maybe the min priority queue class should act as a wrapper class?

T MinPriorityQueue::ExtractMin()
{
  return minHeap.ExtractMin();
}

In that case, the binary min heap class might implement Min(), ExtractMin(), DecreaseKey(), and Insert() and contain the functionality for both a binary min heap and min priority queue. Then there would be no need for a MinPriorityQueue class at all.

The scope of the question is implementing heaps/priority queues for job interviews. Any thoughts on this?

James Miller
  • 25
  • 1
  • 4
  • `std::priority_queue` quite happily implements a priority queue on top of a flat `vector`, with no pointers anywhere. I don't know what CLRS is, but either you misunderstand what it says, or it makes things unnecessarily complicated. – Igor Tandetnik Jan 07 '18 at 20:47
  • Sorry, by CLRS I meant "Introduction to Algorithms, Third Edition". The std::priority_queue doesn't support modifying keys once inserted (as far as I know) so how would you make it work for something like Dijkstra's algorithm? I am also asking for interview purposes, though, in case I have to implement it myself. – James Miller Jan 07 '18 at 21:03
  • Dijkstra's algorithm doesn't require modifying keys once inserted. `std::priority_queue` comes with source code, you can study how it works. – Igor Tandetnik Jan 07 '18 at 21:16

1 Answers1

0

1) Usually you don't want to have to modify your value types just because you want to make a heap of them. You'd make your heap something like this:

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;
};

Then, throughout the implementation of Dijkstra's algorithm you use indexes into the data vector to refer to objects, and you can get each item's heap index with data[itemIndex].heapIndex.

BUT see my answer over here: Prim's Algorithm: How to get index of key on which DECREASE_KEY operation is to be performed? ... I usually implement Dijkstra's algorithm without a decrease_key operation.

2) I don't really see any reason to make a heap class that is separate from the priority queue implementation. I would actually call the class you need a "Heap", though, not a priority queue, since priority queue interfaces don't usually expect the keys to be separate from the objects.

You should use std::make_heap, std::push_heap and std::pop_heap on a vector.

Matt Timmermans
  • 53,709
  • 3
  • 46
  • 87