// $Id: Heap.h,v 1.2 1999/06/05 23:29:16 greear Exp $
// $Revision: 1.2 $ $Author: greear $ $Date: 1999/06/05 23:29:16 $
//
//ScryMUD Server Code
//Copyright (C) 1998 Ben Greear
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// To contact the Author, Ben Greear: greear@cyberhighway.net, (preferred)
// greearb@agcs.com
//
#ifndef BEN_HEAP_H
#define BEN_HEAP_H
#include <KVPair.h>
/** Implemented with an array of KVPair<long, VAL>. The array should
* at all times have one more element than max_len. This is because it
* is logically one's based. The first element... array[0] is used when
* we cannot return anything valid. However, it is up to calling code
* to check for cur_len (getCurSize()) to make sure one can be removed.
* The heap will grow as needed, roughly doubling each time it has to
* be expanded.
*/
template <class VAL> class PtrHeap {
public:
PtrHeap() {
array = new VAL[11]; //we don't use the first one as part of the heap.
cur_len = 0;
max_len = 10;
}//constructor
PtrHeap(const PtrHeap<VAL>& src) {
cur_len = src.cur_len;
max_len = src.max_len;
array = new VAL[max_len+1];
bcopy(array, src.array, sizeof(KVPair<long, VAL>) * cur_len);
}//copy constructor
PtrHeap<VAL>& operator=(const PtrHeap<VAL>& src) {
if (&src != this) {
ensureCapacity(src.cur_len);
cur_len = src.cur_len;
max_len = src.max_len;
bcopy(array, src.array, sizeof(PVPair<long, VAL>) * cur_len);
}//if
return *this;
}//operator=
void insert(long key, VAL val) {
ensureCapacity(cur_len + 1);
cur_len++;
KVPair<long, VAL> kvp(key, val);
long i = cur_len;
long par = 0;
while (i > 1 && (array[i] < kvp)) {
par = getParentIndex(i);
array[i] = array[par];
i = par;
}//while
array[i] = kvp;
}//insert
KVPair<long, VAL> popTopVal() {
if (cur_len < 1) {
return array[0]; //unused otherwise.
}//if
else {
KVPair<long, VAL> retval = array[1];
array[1] = array[cur_len];
cur_len--;
heapify(1);
return max;
}
}//popTopVal
KVPair<long, VAL> peepTopVal() {
if (cur_len < 1) {
return array[0]; //unused otherwise
}//if
else {
return array[1];
}
}//peepTopVal
long getCurSize() { return cur_len; }
long getMaxSize() { return max_len; } //without expanding
void ensureCapacity(long cap) {
if (cap > max_len) {
KVPair<long, VAL>* tmp = array;
array = new KVPair[cap + max_len + 1]; //+1 because we mimic 1's based
bcopy(array, tmp, sizeof(KVPair<long, VAL>) * cur_len);
max_len += cap;
delete[] tmp;
}//if
}//ensureCapacity
protected:
KVPair<long, VAL>& getParent(long of_i) { return array[of_i/2]; }
long getParentIndex(long i) { return i/2; }
KVPair<long, VAL>& getLeftChild(long of_i) { return array[2*i]; }
long getLeftChildIndex(long i) { return 2*i; }
KVPair<long, VAL>& getRightChild(long of_i) { return array[2*i + 1]; }
long getRightChildIndex(long i) { return 2*i +1; }
void heapify(long idx) {
long left = getLeftChildIndex(idx);
long right = getRightChildIndex(idx);
long largest;
if ((left <= cur_len) && (array[left] > array[idx])) {
largest = left;
}
else {
largest = idx;
}
if ((right <= cur_len) && (array[right] > array[largest])) {
largest = right;
}
if (largest != idx) {
KVPair<long, VAL> tmp(array[idx]);
array[idx] = array[largest];
array[largest] = tmp;
heapify(largest); //curse and recurse
}//if
}//heapify
/* Protected variables. */
KVPair<long, VAL>* array;
long max_len;
long cur_len;
private:
}//PtrHeap
#endif