diff --git a/lib/modules/ADT.pmod/heap.pike b/lib/modules/ADT.pmod/heap.pike new file mode 100644 index 0000000000000000000000000000000000000000..2d1873acfe5f7224ed3925a2c156c1f1b147b0ec --- /dev/null +++ b/lib/modules/ADT.pmod/heap.pike @@ -0,0 +1,110 @@ +#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() +{ + int e; + for(e=1;e<num_values;e++) + { + if(values[(e-1)/2] > values[e]) + { + write(sprintf("FEL in HEAP (%d, %d) num_values=%d\n", (e-1)/2, e, num_values)); + exit(1); + } + } +} +#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; + + if(values[elem] < values[parent]) + { + SWAP(elem, parent); + elem=parent; + while(values[elem] < values[parent=(elem -1)/2]) + { + SWAP(elem, parent); + elem=parent; + } + adjust_down(elem); + return 1; + } + return 0; +} + +void push(mixed value) +{ + if(num_values >= sizeof(values)) + values+=allocate(10+sizeof(values)/16); + + values[num_values++]=value; + adjust_up(num_values-1); + verify_heap(); +} + +void adjust(mixed value) +{ + int pos=search(values, value); + if(pos>=0) + if(!adjust_up(pos)) + adjust_down(pos); + verify_heap(); +} + +mixed top() +{ + 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(); +} diff --git a/lib/modules/ADT.pmod/priority_queue.pike b/lib/modules/ADT.pmod/priority_queue.pike new file mode 100644 index 0000000000000000000000000000000000000000..4fd0ed115612aab74282df6ad04a51e9c5d6e544 --- /dev/null +++ b/lib/modules/ADT.pmod/priority_queue.pike @@ -0,0 +1,29 @@ +inherit "heap"; + +class elem { + int pri; + mixed value; + + void create(int a, mixed b) { pri=a; value=b; } + + int `<(object o) { return pri<o->pri; } + int `>(object o) { return pri>o->pri; } + int `==(object o) { return pri==o->pri; } +}; + +mixed push(int pri, mixed val) +{ + mixed handle; + + handle=elem(pri, val); + ::push(handle); + return handle; +} + +void adjust_pri(mixed handle, int new_pri) +{ + handle->pri=new_pri; + ::adjust(handle); +} + +mixed next() { return top()->value; } diff --git a/lib/modules/ADT.pmod/stack.pike b/lib/modules/ADT.pmod/stack.pike new file mode 100644 index 0000000000000000000000000000000000000000..7fd72d8f9417cf5a534aae997d3cd8fd9f39697d --- /dev/null +++ b/lib/modules/ADT.pmod/stack.pike @@ -0,0 +1,45 @@ +#define error(X) throw( ({ (X), backtrace()[0..sizeof(backtrace())-2] }) ) + +int ptr; +mixed *arr=allocate(32); + +void push(mixed val) +{ + if(ptr==sizeof(arr)) arr+=allocate(ptr); + arr[ptr++]=val; +} + +mixed pop(void|int val) +{ + mixed foo; + + if (val) { + if (ptr <= 0) { + error("Stack underflow\n"); + } + + if (ptr < val) { + val = ptr; + } + ptr -= val; + foo = arr[ptr..ptr + val - 1]; + + for (int i=0; i < val; i++) { + arr[ptr + i] = 0; /* Don't waste references */ + } + } else { + if(--ptr < 0) + error("Stack underflow\n"); + + foo=arr[ptr]; + arr[ptr]=0; /* Don't waste references */ + } + return foo; +} + +void reset() +{ + arr=allocate(32); + ptr=0; +} +