// Computer Science 367, Section 3, Fall 1997 // Instructor: Michael Siff (siff@cs.wisc.edu) // // // FILE: pq.C // // // A priority queue template class using heaps implemented with dynamic arrays. // // // INVARIANT for PQueue: // Every node's key is greater than the key of all its children. The tree // remains complete - it's full at all levels but the lowest. next is the // node at which the next insertion should take place. This means that // the dynamic array heap is filled from 0 up to count-1 at all times, // and the key of heap[i] is > heap[2i+1] and heap[2i+2]. And heap[0] // contains the maximum value. #include // Provides assert #include // Provides size_t #include "swap.C" // Private Members (Utilities) // --------------- template size_t PQueue::parent(size_t index) const { assert(index > 0); return ((index-1) / 2); } template size_t PQueue::left(size_t index) const // precondition: hasLeft() is true { return (2*index + 1); } template size_t PQueue::right(size_t index) const // precondition: hasRight() is true { return (2*index + 2); } template bool PQueue::hasLeft(size_t index) const { return (2*index + 1 < count); } template bool PQueue::hasRight(size_t index) const { return (2*index + 2 < count); } template void PQueue::heapifyUp(size_t index) // starts at node indicated by index and works up until heap property is // satisfied. { for(size_t i=index; i>0 && (heap[parent(i)].k < heap[i].k); i = parent(i)) swap(heap[parent(i)], heap[i]); } template void PQueue::heapifyDown(size_t index) // starts at node indicated by index and works down until heap property is // satisfied. { bool done=false; size_t i = index; size_t largest; do { largest = i; if (hasLeft(i) && heap[i].k < heap[left(i)].k) largest = left(i); if (hasRight(i) && heap[largest].k < heap[right(i)].k) largest = right(i); if (largest != i) { swap(heap[i], heap[largest]); i = largest; } else done = true; } while (!done); } // Constructors // ------------ // Default Constructor template PQueue::PQueue() { heap = new IKP[INITIAL_CAPACITY]; count = 0; capacity = INITIAL_CAPACITY; } // Copy Constructor template PQueue::PQueue(const PQueue& source) { heap = new IKP[source.capacity]; count = source.count; capacity = source.capacity; for(size_t i = 0; i < count; i++) heap[i] = source.heap[i]; } // Destructor // ---------- template PQueue::~PQueue() { delete[] heap; } // CONSTANT MEMBER FUNCTIONS // ------------------------- template size_t PQueue::size() const { return (count); } template bool PQueue::isEmpty() const { return(count==0); } template Item PQueue::maximum() const // Returns a copy of the highest priority item. { assert(!isEmpty()); return (heap[0]); } // MODIFICATION MEMBER FUNCTIONS // ----------------------------- template void PQueue::insert(const Item& it, const Key& priority) // Places a copy of item-key pair on priority queue. Doubles the capacity of // the heap if the count reaches former capacity. { heap[count].val = it; heap[count].k = priority; heapifyUp(count); count++; if (count==capacity) { capacity = capacity * 2; IKP *temp = new IKP[capacity]; for(size_t i=0; i < count; i++) temp[i] = heap[i]; delete[] heap; heap = temp; } } template Item PQueue::extractMax() // Removes and returns a copy of the item of highest priority. { assert(!isEmpty()); Item result = heap[0].val; count--; heap[0] = heap[count]; heapifyDown(0); return result; } template void PQueue::operator=(const PQueue& source) { if (capacity != source.capacity) { delete[] heap; heap = new IKP[source.capacity]; capacity = source.capacity; } count = source.count; for(size_t i = 0; i < count; i++) heap[i] = source.heap[i]; }