Mercurial > projects > aid
diff trunk/aid/containers/heap.d @ 0:4b2e8e8a633e
Repository setup.
author | revcompgeek |
---|---|
date | Mon, 03 Mar 2008 19:28:10 -0700 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/aid/containers/heap.d Mon Mar 03 19:28:10 2008 -0700 @@ -0,0 +1,282 @@ +/*++++++++++++++++++++++++++++++++++++++++++++ + + Heap sorted array + + + By Matt Peterson + + ++++++++++++++++++++++++++++++++++++++++++++*/ + +/*class Heap(Value) { + Value[] array; + int tail; + public int capacity(){ + // This returns the current capacity of the heap. + return array.length; + } + public int size(){ + // This returns the number of items in the heap. + return tail; + } + + void capacity(int c){ + // This sets the capacity to c. + if(c < tail) c = tail; + array.length = c; + } + void insert(Value v){ + // Inserts a value and sorts it to it's correct position. + if(tail >= size()) capacity(size()+10); + array[++tail] = v; + int i = tail; + while(i > 0 && array[i/2] > array[i]){ + array[i] = array[i/2]; + array[i/2] = v; + i /= 2; + } + } + Value removeHead(){ + Value ret = array[0]; + array[0] = array[tail]; + tail--; + i = 0; + while( + } + +}*/ + +struct Heap(Value, Alloc = GCAllocator) { + + alias ArrayHeap ContainerType; + alias Value ValueType; + alias size_t IndexType; + + Value[] data; ///< backing array. null by default, grows as needed + + invariant { + assert( tail <= data.length ); + } + + /** signature for a custom comparison function */ + alias int delegate(Value* a, Value* b) CompareFcn; + + /** Set custom comparison function. */ + void compareFcn(CompareFcn cmp) { + cmpFcn = cmp; + } + + /** Get heap contents as dynamic array slice of backing array. */ + Value[] values() { + return data[0..tail]; + } + + /** Adds an item to the heap. Increases capacity if needed. */ + void addTail(Value v) { + capacity(tail+1); + data[tail++] = v; + fixupTail(); + } + + /** Removes and returns the head item of the heap. If the target + * heap is empty an IndexOutOfBoundsException is thrown unless + * version=MinTLNoIndexChecking is set. + */ + Value takeHead() { + version (MinTLNoIndexChecking) { + // no error checking + } else { + if (tail == 0) + throw new IndexOutOfBoundsException(); + } + Value val = data[0]; + data[0] = data[--tail]; + data[tail] = Value.init; + fixupHead(); + return val; + } + + /** Removes the head item of the heap. */ + void removeHead() { + version (MinTLNoIndexChecking) { + // no error checking + } else { + if (tail == 0) + throw new IndexOutOfBoundsException(); + } + data[0] = data[--tail]; + data[tail] = Value.init; + fixupHead(); + } + + /** Get the length of heap. */ + size_t length() { + return tail; + } + + /** Test if container is empty. */ + bool isEmpty() { + return tail == 0; + } + + /** Clear all contents. */ + void clear() { + static if (is(Alloc == GCAllocator)) { + } else { + if (data.ptr) + Alloc.gcFree(data.ptr); + } + *this = ArrayHeap.init; + } + + /** Get the nth item in the heap from head. */ + Value opIndex(size_t n) { + return data[n]; + } + + /** Get a pointer to the nth item in the heap */ + Value* lookup(size_t n) { + return &data[n]; + } + + /** Set the nth item in the heap. */ + void opIndexAssign(Value val, size_t n) { + data[n] = val; + } + + /** Duplicates a heap. */ + ArrayHeap dup() { + ArrayHeap res; + static if (is(Alloc == GCAllocator)) { + res.data = data.dup; + } else { + Value* p = cast(Value*)Alloc.malloc(data.length * Value.sizeof); + res.data = p[0 .. data.length]; + res.data[] = data[]; + } + res.tail = tail; + res.cmpFcn = cmpFcn; + return res; + } + + /** Test for equality of two heaps. */ + int opEquals(ArrayHeap c) { + size_t len = length; + if (len !is c.length) + return 0; + size_t a,b; + a = 0; + b = 0; + TypeInfo ti = typeid(Value); + for (size_t k = 0; k < len; k++) { + if (!ti.equals(&data[a],&c.data[b])) + return 0; + a++; + b++; + } + return 1; + } + + /** Compare two heaps. */ + int opCmp(ArrayHeap c) { + size_t len = length; + if (len > c.length) + len = c.length; + size_t a,b; + a = 0; + b = 0; + TypeInfo ti = typeid(Value); + for (size_t k = 0; k < len; k++) { + int cmp = ti.compare(&data[a],&c.data[b]); + if (cmp) + return cmp; + a++; + b++; + } + return cast(int)length - cast(int)c.length; + } + + /** Returns a short string representation of the heap. */ + char[] toString() { + return "[ArrayHeap length " ~ std.string.toString(tail) ~ "]"; + } + + /** Iterates over the heap from head to tail calling delegate to + * perform an action. The value is passed to the delegate. + */ + int opApplyNoKey(int delegate(inout Value x) dg){ + int res = 0; + for (size_t k=0; k < tail; k++) { + res = dg(data[k]); + if (res) break; + } + return res; + } + + /** Iterates over the heap from head to tail calling delegate to + * perform an action. The index from 0 and the value are passed + * to the delegate. + */ + int opApplyWithKey(int delegate(inout size_t n, inout Value x) dg){ + int res = 0; + for (size_t k=0; k < tail; k++) { + res = dg(k,data[k]); + if (res) break; + } + return res; + } + + alias opApplyNoKey opApply; + alias opApplyWithKey opApply; + + /** Ensure the minimum capacity of heap. */ + void capacity(size_t cap) { + if (cap > data.length) { + cap = (cap+1)*2; + static if (is(Alloc == GCAllocator)) { + data.length = cap; + } else { + Value* p = data.ptr; + p = cast(Value*)Alloc.gcRealloc(p,cap*Value.sizeof); + p[data.length .. cap] = Value.init; + data = p[0 .. cap]; + } + } + } + + // Helper functions + + // enforce heap invariant after a new head + private void fixupHead() { + size_t n = 0; + TypeInfo ti = typeid(Value); + if (cmpFcn is null) { + cmpFcn = cast(CompareFcn)&ti.compare; + } + for (;;) { + size_t n1 = 2*n+1; + if (n1 >= tail) break; + if ((n1 != tail-1) && (cmpFcn(&data[n1],&data[n1+1]) < 0)) + n1++; + if (cmpFcn(&data[n],&data[n1]) < 0) { + ti.swap(&data[n],&data[n1]); + n = n1; + } else { + break; + } + } + } + + // enforce heap invariant after a new tail + private void fixupTail() { + size_t n = tail-1; + TypeInfo ti = typeid(Value); + if (cmpFcn is null) { + cmpFcn = cast(CompareFcn)&ti.compare; + } + size_t n1 = (n-1)>>1; + while ((n > 0) && (cmpFcn(&data[n],&data[n1]) > 0)) { + ti.swap(&data[n],&data[n1]); + n = n1; + n1 = (n-1)>>1; + } + } + + private CompareFcn cmpFcn; + private size_t tail; +} \ No newline at end of file