// heap_a.cc
#include < stdlib.h >
#include "heap_a.h"

Heap::Heap (int size, reallong (*v)(void *)) {
   value = v;
   objects = new void*[size];
   this->size = size;
   tail = 0;
}

bool Heap::isEmpty () { return tail == 0; }

void Heap::insert (void *obj) {
   if (obj == NULL) return;
   int ptr = tail;
   objects[tail++] = obj;
   while ((ptr-1)/2 >= 0 && value(objects[ptr]) < value(objects[(ptr-1)/2])) {
      void *t = objects[ptr];
      objects[ptr] = objects[(ptr-1)/2];
      objects[(ptr-1)/2] = t;
      ptr = (ptr-1)/2;
   }
}

void *Heap::dequeue () {
   if (tail == 0) return NULL;
   void *t = objects[0];
   objects[0] = objects[--tail];
   int ptr = 0;
   while (2*(ptr+1) <= tail) {
      void *p = objects[ptr];
      if (value(objects[(ptr+1)*2-1]) < value(objects[ptr])) {
	 if (value(objects[(ptr+1)*2-1]) < value(objects[(ptr+1)*2])) {
	    objects[ptr] = objects[(ptr+1)*2-1];
	    objects[(ptr+1)*2-1] = p;
	    ptr = (ptr+1)*2-1;
	 } else {
	    objects[ptr] = objects[(ptr+1)*2];
	    objects[(ptr+1)*2] = p;
	    ptr = (ptr+1)*2;
	 }
      } else if (2*(ptr+1) < tail) {
	 if (value(objects[(ptr+1)*2]) < value(objects[ptr])) {
	    objects[ptr] = objects[(ptr+1)*2];
	    objects[(ptr+1)*2] = p;
	    ptr = (ptr+1)*2;
	 } else break;
      } else break;
   }
   return t;
}