a580e12000-09-27Fredrik Hübinette (Hubbe) #pike __REAL_VERSION__
a20af62000-09-26Fredrik Hübinette (Hubbe) 
a523ea2006-04-24Robert Hinn //! This class implements a (min-)heap. The value of a child node will //! always be greater than or equal to the value of its parent node. //! Thus, the top node of the heap will always hold the smallest value.
b78e3a1999-12-30Fredrik Hübinette (Hubbe) #define SWAP(X,Y) do{ mixed tmp=values[X]; values[X]=values[Y]; values[Y]=tmp; }while(0) static private array values=allocate(10); static private int num_values; #ifdef DEBUG void verify_heap() {
ab3b6d2003-05-03Martin Nilsson  for(int e=1; e<num_values; e++)
b78e3a1999-12-30Fredrik Hübinette (Hubbe)  if(values[(e-1)/2] > values[e])
ab3b6d2003-05-03Martin Nilsson  error("Error in HEAP (%d, %d) num_values=%d\n", (e-1)/2, e, num_values);
b78e3a1999-12-30Fredrik Hübinette (Hubbe) } #else #define verify_heap() #endif static void adjust_down(int elem) { int steps; while(1) { int child=elem*2+1; if(child >= num_values) break; if(child+1==num_values || values[child] < values[child+1]) { if(values[child] < values[elem]) { SWAP(child, elem); elem=child; continue; } } else { if(child+1 >= num_values) break; if(values[child+1] < values[elem]) { SWAP(elem, child+1); elem=child+1; continue; } } break; } } static int adjust_up(int elem) { int parent=(elem-1)/2;
4720a61999-12-30Fredrik Hübinette (Hubbe) 
af00351999-12-31Fredrik Hübinette (Hubbe)  if(elem && values[elem] < values[parent])
b78e3a1999-12-30Fredrik Hübinette (Hubbe)  { SWAP(elem, parent); elem=parent;
af00351999-12-31Fredrik Hübinette (Hubbe)  while(elem && (values[elem] < values[parent=(elem -1)/2]))
b78e3a1999-12-30Fredrik Hübinette (Hubbe)  { SWAP(elem, parent); elem=parent; } adjust_down(elem); return 1; } return 0; }
a523ea2006-04-24Robert Hinn //! Push an element onto the heap. The heap will automatically sort itself //! so that the smallest value will be at the top.
b78e3a1999-12-30Fredrik Hübinette (Hubbe) void push(mixed value) { if(num_values >= sizeof(values))
4720a61999-12-30Fredrik Hübinette (Hubbe)  values+=allocate(10+sizeof(values)/4);
b78e3a1999-12-30Fredrik Hübinette (Hubbe)  values[num_values++]=value; adjust_up(num_values-1); verify_heap(); }
a523ea2006-04-24Robert Hinn //! Takes a value in the heap and sorts it through the heap to maintain //! its sort criteria (increasing order).
b78e3a1999-12-30Fredrik Hübinette (Hubbe) void adjust(mixed value) { int pos=search(values, value); if(pos>=0) if(!adjust_up(pos)) adjust_down(pos); verify_heap(); }
ab3b6d2003-05-03Martin Nilsson //! Removes and returns the item on top of the heap, //! which also is the smallest value in the heap. mixed pop()
b78e3a1999-12-30Fredrik Hübinette (Hubbe) { mixed ret; if(!num_values) error("Heap underflow!\n"); ret=values[0]; if(sizeof(values) > 1) { num_values--; values[0]=values[num_values]; values[num_values]=0; adjust_down(0); if(num_values * 3 + 10 < sizeof(values)) values=values[..num_values+10]; } return ret; verify_heap(); }
ab3b6d2003-05-03Martin Nilsson //! Returns the number of elements in the heap. int _sizeof() { return num_values; }
b78e3a1999-12-30Fredrik Hübinette (Hubbe) 
ab3b6d2003-05-03Martin Nilsson // compat
a523ea2006-04-24Robert Hinn //! Removes and returns the item on top of the heap, //! which also is the smallest value in the heap.
ab3b6d2003-05-03Martin Nilsson mixed top() { return pop(); }
a523ea2006-04-24Robert Hinn  // compat //! Returns the number of elements in the heap.
ab3b6d2003-05-03Martin Nilsson int size() { return _sizeof(); }
a523ea2006-04-24Robert Hinn  //! Returns the item on top of the heap (which is also the smallest value //! in the heap) without removing it. mixed peek() { if (!num_values) return UNDEFINED; return values[0]; }