parent $frob_class
object $heap_class
var $root child_index 0
var $root owners [$heap_class]
var $root owned [$heap_class]
var $root fertile 0
var $root inited 1
var $root manager $heap_class
var $root writable [$heap_class]
var $root readable ['parameters, 'methods, 'code]
var $root dbref 'heap_class
method new
arg list, [key];
var ret_heap;
// returns list as a valid heap sorted on key || 1
key = [@key, 1][1];
if (!list)
return <this(), #[['key, key], ['data, []]]>;
ret_heap = .new([], key);
while (list) {
ret_heap = ret_heap.add(list[1]);
list = delete(list, 1);
}
return ret_heap;
.
method data
arg self;
return self['data];
.
method should_swap
arg self, element1, element2;
// returns true iff data[element2] should appear earlier in the list to maintain
// consistent data structure.
// re-define in children of $heap_class to adjust sort order
return 0;
.
method swap
arg self, a, b;
return <this(), self.replace('data, $list.swap(self['data], a, b))>;
.
method add
arg self, element;
var swap, cur_element, element_above;
// add element to self
// tack it on the end and change self from rep (a dict) to heap_class
self = <this(), self.replace('data, (self['data]) + [element])>;
// loop percolates new element up
cur_element = self.length();
element_above = cur_element / 2;
swap = 1;
while (element_above && swap) {
if (self.should_swap(element_above, cur_element))
self = self.swap(element_above, cur_element);
else
swap = 0;
cur_element = element_above;
element_above = cur_element / 2;
}
return self;
.
method del
arg self, element;
var data, cur_element, next_element, len;
// remove element'th element from self
// this method works by pushing element down the heap, swapping it with
// the element below it that should be on top (of the two).
// self rep changed to frob for swapping
self = <this(), self>;
// data = self['data];
len = self.length();
if ((element > len) || (element < 1))
throw(~range, "Element index out of range.");
cur_element = element;
next_element = cur_element * 2;
while (next_element < len) {
if (self.should_swap(next_element, next_element + 1))
next_element = next_element + 1;
self = self.swap(cur_element, next_element);
cur_element = next_element;
next_element = cur_element * 2;
}
// if it didn't trickle down to the end...
if (cur_element != len) {
// swap cur w/ last (so we can delete it)
self = self.swap(cur_element, len);
// tricle swapped element up
next_element = cur_element / 2;
while (next_element) {
if (self.should_swap(next_element, cur_element))
self = self.swap(next_element, cur_element);
else
next_element = 0;
cur_element = next_element;
next_element = cur_element / 2;
}
}
self = self._drop_last();
return self;
.
method _drop_last
arg rep;
if (!(rep['data]))
throw(~range, "Attempt to kill last element of null heap.");
return <this(), rep.replace('data, delete(rep['data], listlen(rep['data])))>;
.
method element
arg self, index;
return (self['data])[index];
.
method length
arg self;
return listlen(self['data]);
.
method heaped
arg self;
var element;
// returns true if data structure is consistent
if (!(self['data]))
return 1;
element = 1;
// loop through elements
while (1) {
if ((!(| .should_swap(self, element, element * 2) |)) && (!(| .should_swap(self, element, (element * 2) + 1) |)))
element = element + 1;
else
return 0;
if (element >= ((.length(self)) / 2))
return 1;
}
.