// // HtHeap.cc // // HtHeap: A Heap class which holds objects of type Object. // (A heap is a semi-ordered tree-like structure. // it ensures that the first item is *always* the largest. // NOTE: To use a heap, you must implement the Compare() function for // your Object classes. The assumption used here is -1 means // less-than, 0 means equal, and +1 means greater-than. Thus // this is a "min heap" for that definition.) // // Part of the ht://Dig package // Copyright (c) 1999-2004 The ht://Dig Group // For copyright details, see the file COPYING in your distribution // or the GNU Library General Public License (LGPL) version 2 or later // // // $Id: HtHeap.cc,v 1.12 2004/05/28 13:15:20 lha Exp $ // #ifdef HAVE_CONFIG_H #include "htconfig.h" #endif /* HAVE_CONFIG_H */ #include "HtHeap.h" #ifdef HAVE_STD #include #ifdef HAVE_NAMESPACES using namespace std; #endif #else #include #endif /* HAVE_STD */ //********************************************************************* // void HtHeap::HtHeap() // Default constructor // HtHeap::HtHeap() { data = new HtVector; } //********************************************************************* // void HtHeap::HtHeap(HtVector vector) // Constructor from vector // (has the side effect of not allocating double memory) // HtHeap::HtHeap(HtVector vector) { int size = vector.Count(); data = static_cast(vector.Copy()); // Now we have to "heapify" -- start at the first interior node // And push each node down into its subtree // (This is O(n)!) for (int i = parentOf(size); i >= 0; i--) pushDownRoot(i); } //********************************************************************* // void HtHeap::~HtHeap() // Destructor // HtHeap::~HtHeap() { Destroy(); } //********************************************************************* // void HtHeap::Destroy() // Deletes all objects from the heap // void HtHeap::Destroy() { data->Destroy(); delete data; } //********************************************************************* // void HtHeap::Add(Object *object) // Add an object to the heap. // void HtHeap::Add(Object *object) { data->Add(object); percolateUp(data->Count() - 1); } //********************************************************************* // Object *HtHeap::Remove() // Remove an object from the top of the heap // This requires re-heapifying by placing the last element on the top // and pushing it down. // Object *HtHeap::Remove() { Object *min = Peek(); data->Assign(data->Last(), 0); data->RemoveFrom(data->Count()-1); if (data->Count() > 1) pushDownRoot(0); return min; } //********************************************************************* // HtHeap *HtHeap::Copy() const // Return a deep copy of the heap. // Object *HtHeap::Copy() const { HtHeap *heap = new HtHeap(*data); return heap; } //********************************************************************* // HtHeap &HtHeap::operator=(HtHeap &heap) // Return a deep copy of the heap. // HtHeap &HtHeap::operator=(HtHeap &heap) { Destroy(); data = heap.data; return *this; } //********************************************************************* // voide HtHeap::percolateUp(int leaf) // Pushes the node pointed to by leaf upwards // it will travel as far as possible upwards to ensure the data is a heap // void HtHeap:: percolateUp(int leaf) { int parent = parentOf(leaf); Object *value = data->Nth(leaf); while (leaf > 0 && (value->compare(*(data->Nth(parent))) < 0)) { data->Assign(data->Nth(parent), leaf); leaf = parent; parent = parentOf(leaf); } data->Assign(value, leaf); } //********************************************************************* // void HtHeap::pushDownRoot(int root) // Pushes the node pointed to by root into the heap // it will go down as far as necessary to ensure the data is a heap // void HtHeap::pushDownRoot(int root) { int size = data->Count() - 1; Object *value = data->Nth(root); while (root < size) { int childPos = leftChildOf(root); if (childPos < size) { if ( rightChildOf(root) < size && data->Nth(childPos + 1)->compare(*(data->Nth(childPos))) < 0 ) { childPos++; } if ( data->Nth(childPos)->compare(*value) < 0 ) // -1, so smaller { // We have to swap this node with the root and then loop data->Assign(data->Nth(childPos), root); data->Assign(value, childPos); root = childPos; } else { // Found the right position, so we're done data->Assign(value, root); return; } } else // childPos >= heapSize { // At a leaf, so we're done data->Assign(value, root); return; } } }