Mercurial > projects > ddbg_continued
view src/container.d @ 1:4a9dcbd9e54f
-files of 0.13 beta
-fixes so that it now compiles with the current dmd version
author | marton@basel.hu |
---|---|
date | Tue, 05 Apr 2011 20:44:01 +0200 |
parents | |
children |
line wrap: on
line source
/* Ddbg - Win32 Debugger for the D programming language * Copyright (c) 2007 Jascha Wetzel * All rights reserved. See LICENSE.TXT for details. */ import std.string; debug import std.stdio; /******************************************************************************* Double linked list *******************************************************************************/ class List(T) { class Element { T value; Element prev, next; this(T v) { value = v; } } Element head, tail; List opCatAssign(T v) { if ( tail is null ) head = tail = new Element(v); else { tail.next = new Element(v); tail.next.prev = tail; tail = tail.next; } return this; } bool empty() { return head is null; } void clear() { head = null; tail = null; } void remove(Element e) { if ( e is null ) return; assert(e !is null); if ( e.prev is null ) head = e.next; else e.prev.next = e.next; if ( e.next is null ) tail = e.prev; else e.next.prev = e.prev; } int opApply(int delegate(inout Element) dg) { for ( Element e=head; e !is null; e = e.next ) { int ret = dg(e); if ( ret ) return ret; } return 0; } int opApplyReverse(int delegate(inout Element) dg) { for ( Element e=tail; e !is null; e = e.prev ) { int ret = dg(e); if ( ret ) return ret; } return 0; } } /************************************************************************************************** AVL Tree that balances itself after each insertion **************************************************************************************************/ class AVLTree(T) { alias AVLNode!(T) node_t; node_t root; bool rebalance; bool insert(T v) { if ( root is null ) { root = new AVLNode!(T)(v); return true; } else { rebalance = false; return insert(root, v); } } bool find(VT,RT)(VT v, out RT res) { if ( root is null ) return false; return root.find(v, res); } void traverseDepthLeft(RT)(bool delegate(RT v) proc) { if ( root !is null ) root.traverseDepthLeft(proc); } private bool insert(node_t n, T v) { void updateParents(node_t top=null) { with ( n ) { if ( top is null ) top = n; balance = 0; parent.balance = 0; node_t pp = parent.parent; if ( pp is null ) root = top; else { if ( parent is pp.left ) pp.left = top; else pp.right = top; } parent.parent = top; top.parent = pp; if ( top !is n ) parent = top; } } with ( n ) { if ( v < value ) { if ( left is null ) { left = new node_t(v, n); --balance; if ( balance != 0 ) rebalance = true; } else if ( !insert(left, v) ) return false; } else if ( v > value ) { if ( right is null ) { right = new node_t(v, n); ++balance; if ( balance != 0 ) rebalance = true; } else if ( !insert(right, v) ) return false; } else return false; if ( rebalance && parent !is null ) { assert(balance != 0); if ( n is parent.left ) { if ( parent.balance > 0 ) --parent.balance; else if ( parent.balance == 0 ) { --parent.balance; return true; } else { // single rotation to the right if ( balance < 0 ) { parent.left = right; if ( right !is null ) right.parent = parent; right = parent; updateParents; } // double rotation to the right else { assert(right !is null); node_t r = right; parent.left = r.right; if ( parent.left !is null ) parent.left.parent = parent; right = r.left; if ( right !is null ) right.parent = n; r.right = parent; r.left = n; updateParents(r); } } } else { if ( parent.balance < 0 ) ++parent.balance; else if ( parent.balance == 0 ) { ++parent.balance; return true; } else { // single rotation to the left if ( balance > 0 ) { parent.right = left; if ( left !is null ) left.parent = parent; left = parent; updateParents; } // double rotation to the left else { assert(left !is null); node_t l = left; parent.right = l.left; if ( parent.right !is null ) parent.right.parent = parent; left = l.right; if ( left !is null ) left.parent = n; l.left = parent; l.right = n; updateParents(l); } } } } rebalance = false; return true; } } } class AVLNode(T) { alias AVLNode!(T) node_t; node_t parent, left, right; byte balance; T value; this(T v, node_t p = null) { value = v; parent = p; } void traverseDepthLeft(RT)(bool delegate(RT v) proc) { if ( left !is null ) left.traverseDepthLeft(proc); static if ( is(RT == AVLNode!(T)) ) { if ( !proc(this) ) return; } static if ( is(RT == T) ) { if ( !proc(value) ) return; } static if ( !is(RT == AVLNode!(T)) && !is(RT == T) ) static assert(0, "invalid result type for tree traversal"); if ( right !is null ) right.traverseDepthLeft(proc); } bool findNext(RT)(inout RT res) { node_t n; if ( right is null ) { bool found=false; for ( n = this; n.parent !is null; n = n.parent ) { if ( n.parent.left is n ) { static if ( is(T : Object) ) assert(n.parent.value > n.value, "\n"~n.parent.value.toString~" parent of "~n.value.toString~"\n"); assert(n.parent.value > n.value); n = n.parent; found = true; break; } assert(n.parent.value <= n.value); } if ( !found ) return false; } else { assert(right.value >= value); n = right; while ( n.left !is null ) { static if ( is(T : Object) ) assert(n.left.value < n.value, "\n"~n.left.value.toString~"\tleft of\t"~n.value.toString~"\n"); assert(n.left.value < n.value); n = n.left; } } static if ( is(RT == AVLNode!(T)) ) res = n; static if ( is(RT == T) ) res = n.value; static if ( !is(RT == AVLNode!(T)) && !is(RT == T) ) static assert(0, "invalid result type for next node search"); return true; } bool findPrev(RT)(inout RT res) { node_t n; if ( left is null ) { bool found=false; for ( n = this; n.parent !is null; n = n.parent ) { if ( n.parent.right is n ) { static if ( is(T : Object) ) assert(n.parent.value > n.value, "\n"~n.parent.value.toString~" parent of "~n.value.toString~"\n"); assert(n.parent.value <= n.value); n = n.parent; found = true; break; } assert(n.parent.value <= n.value); } if ( !found ) return false; } else { assert(left.value < value); n = left; while ( n.right !is null ) { static if ( is(T : Object) ) assert(n.right.value < n.value, "\n"~n.right.value.toString~"\tleft of\t"~n.value.toString~"\n"); assert(n.right.value < n.value); n = n.right; } } static if ( is(RT == AVLNode!(T)) ) res = n; static if ( is(RT == T) ) res = n.value; static if ( !is(RT == AVLNode!(T)) && !is(RT == T) ) static assert(0, "invalid result type for prev node search"); return true; } bool find(VT,RT)(VT v, inout RT res) { bool suc; if ( value > v ) { if ( left !is null ) return left.find(v, res); } else if ( value < v ) { if ( right !is null ) return right.find(v, res); } else suc = true; static if ( is(RT == AVLNode!(T)) ) res = this; static if ( is(RT == T) ) res = value; static if ( !is(RT == AVLNode!(T)) && !is(RT == T) ) static assert(0, "invalid result type for tree search"); return suc; } } unittest { AVLTree!(int) tree = new AVLTree!(int); for ( int i = 0; i < 100; ++i ) tree.insert(i); bool checkOrder(AVLNode!(int) n) { if ( n.left !is null ) { assert(n.left.parent is n); assert(n.left.value < n.value); } if ( n.right !is null ) { assert(n.right.parent is n); assert(n.right.value >= n.value); } return true; } tree.traverseDepthLeft(&checkOrder); // check next for ( int i = 0; i < 99; ++i ) { AVLNode!(int) n; assert(tree.find(i, n)); assert(n.value == i); assert(n.findNext(n)); assert(n.value == i+1, .toString(i+1)~" expected, "~.toString(n.value)~" found"); } tree = new AVLTree!(int); for ( int i = 99; i >= 0; --i ) tree.insert(i); tree.traverseDepthLeft(&checkOrder); // check next for ( int i = 0; i < 99; ++i ) { AVLNode!(int) n; assert(tree.find(i, n)); assert(n.value == i); assert(n.findNext(n)); assert(n.value == i+1, .toString(i+1)~" expected, "~.toString(n.value)~" found"); } }