From: megacz Date: Fri, 30 Jan 2004 07:42:00 +0000 (+0000) Subject: 2003/11/21 03:38:09 X-Git-Tag: RC3~321 X-Git-Url: http://git.megacz.com/?a=commitdiff_plain;h=a7e03eb5d3f7c6f66993af80e1b08af34a70a7e9;p=org.ibex.core.git 2003/11/21 03:38:09 darcs-hash:20040130074200-2ba56-0755fc06deaca54e420628edf3d16cb815c6d7a6.gz --- diff --git a/src/org/xwt/util/RedBlackTree.java b/src/org/xwt/util/RedBlackTree.java new file mode 100644 index 0000000..c848f64 --- /dev/null +++ b/src/org/xwt/util/RedBlackTree.java @@ -0,0 +1,301 @@ +// Copyright 2003 Adam Megacz, see the COPYING file for licensing [GPL] +package org.xwt.util; + +/** a red-black tree of arbitrary objects */ +public class RedBlackTree { + + private static boolean RED = false; + private static boolean BLACK = true; + + // These arrays are indexed by "slot", a totally meaningless number + // assigned to each object object[slot] has index index[slot] and + // color color[slot]. Note that slot 0 is reserved as "null". + + /** every object in the tree has an entry here; ordering is completely random */ + private Object[] objects; + + /** the color of each object */ + private boolean[] color; + + /** the slot of this object's parent */ + private int[] parent; + + /** the slot of this object's left child */ + private int[] left; + + /** the slot of this object's right child */ + private int[] right; + + /** the index of each element; ie how many objects are "before" it in the logical ordering */ + private int[] index; + + /** the slot of the root element */ + private int root = 0; + + /** returns the slot of the newly-inserted object */ + /* + public int insertBefore(int slot, Object newObject) { left = cell; cell.parent = this; cell.fixAfterInsertion(); } + public int insertAfterMe(int slot, Object newObject) { right = cell; cell.parent = this; cell.fixAfterInsertion(); } + + private void setColor(int slot, boolean c) { if (objects[slot] != null) color[slot] = c; } + + // FIXME: we can drop all this since all the 0th elements are the defaults, right? + private boolean color(int slot) { return objects[slot] == null ? BLACK : color[slot]; } + private int left(int slot) { return objects[slot] == null ? 0 : left[slot]; } + private int right(int slot) { return objects[slot] == null ? 0 : right[slot]; } + + public void remove(int slot) { remove(slot, index[slot], root); } + + private void seek(int slot, int idx, int cur, int operation) { + if (index[cur] > idx) { + remove(slot, idx, left[cur], operation); + } else if (index[cur] < idx) { + remove(slot, idx, right[cur], operation); + } else { + switch(operation) { + case REMOVE: + case INSERT: + } + } + } + + public void removeNode() { + + // handle case where we are only node + if (left == null && right == null && parent == null) return; + + // if strictly internal, swap places with a successor + if (left != null && right != null) swapPosition(this, nextSibling()); + + // Start fixup at replacement node (normally a child). + // But if no children, fake it by using self + if (left == null && right == null) { + + if (test(BLACK)) fixAfterDeletion(); + + // Unlink (Couldn't before since fixAfterDeletion needs parent ptr) + + if (parent != null) { + if (this == parent.left) + parent.left = null; + else if (this == parent.right) + parent.right = null; + parent = null; + } + + } else { + Box replacement = left; + if (replacement == null) replacement = right; + + // link replacement to parent + replacement.parent = parent; + + if (parent == null) root = replacement; + else if (this == parent.left) parent.left = replacement; + else parent.right = replacement; + + left = null; + right = null; + parent = null; + + // fix replacement + if (test(BLACK)) replacement.fixAfterDeletion(); + + } + } + + // Swap the linkages of two nodes in a tree. + void swapPosition(Box x, Box y) { + + // Too messy. TODO: find sequence of assigments that are always OK + + Box px = x.parent; + boolean xpl = px != null && x == px.left; + Box lx = x.left; + Box rx = x.right; + + Box py = y.parent; + boolean ypl = py != null && y == py.left; + Box ly = y.left; + Box ry = y.right; + + if (x == py) { + y.parent = px; + if (px != null) if (xpl) px.left = y; else px.right = y; + x.parent = y; + if (ypl) { + y.left = x; + y.right = rx; if (rx != null) rx.parent = y; + } + else { + y.right = x; + y.left = lx; if (lx != null) lx.parent = y; + } + x.left = ly; if (ly != null) ly.parent = x; + x.right = ry; if (ry != null) ry.parent = x; + + } else if (y == px) { + x.parent = py; + if (py != null) if (ypl) py.left = x; else py.right = x; + y.parent = x; + if (xpl) { + x.left = y; + x.right = ry; if (ry != null) ry.parent = x; + } + else { + x.right = y; + x.left = ly; if (ly != null) ly.parent = x; + } + y.left = lx; if (lx != null) lx.parent = y; + y.right = rx; if (rx != null) rx.parent = y; + + } else { + x.parent = py; if (py != null) if (ypl) py.left = x; else py.right = x; + x.left = ly; if (ly != null) ly.parent = x; + x.right = ry; if (ry != null) ry.parent = x; + + y.parent = px; if (px != null) if (xpl) px.left = y; else px.right = y; + y.left = lx; if (lx != null) lx.parent = y; + y.right = rx; if (rx != null) rx.parent = y; + } + + boolean c = x.test(BLACK); + if (y.test(BLACK)) x.set(BLACK); else x.clear(BLACK); + if (c) y.set(BLACK); else y.clear(BLACK); + + if (root == x) root = y; + else if (root == y) root = x; + } + + void rotateLeft() { + Box r = right; + right = r.left; + if (r.left != null) r.left.parent = this; + r.parent = parent; + if (parent == null) root = r; + else if (parent.left == this) parent.left = r; + else parent.right = r; + r.left = this; + parent = r; + } + + void rotateRight() { + Box l = left; + left = l.right; + if (l.right != null) l.right.parent = this; + l.parent = parent; + if (parent == null) root = l; + else if (parent.right == this) parent.right = l; + else parent.left = l; + l.right = this; + parent = l; + } + + void fixAfterInsertion() { + clear(BLACK); + Box x = this; + + while (x != null && x != root && !x.parent.test(BLACK)) { + if (parent[x] == left(parent[parent[x]])) { + Box y = right(parent[parent[x]]); + if (color(y) == RED) { + setColor(parent[x], BLACK); + setColor(y, BLACK); + setColor(parent[parent[x]], RED); + x = parent[parent[x]]; + } + else { + if (x == right(parent[x])) { + x = parent[x]; + x.rotateLeft(); + } + setColor(parent[x], BLACK); + setColor(parent[parent[x]], RED); + if (parent[parent[x]] != null) + parent[parent[x]].rotateRight(); + } + } + else { + Box y = left(parent[parent[x]]); + if (color(y) == RED) { + setColor(parent[x], BLACK); + setColor(y, BLACK); + setColor(parent[parent[x]], RED); + x = parent[parent[x]]; + } + else { + if (x == left(parent[x])) { + x = parent[x]; + x.rotateRight(); + } + setColor(parent[x], BLACK); + setColor(parent[parent[x]], RED); + if (parent[parent[x]] != null) + parent[parent[x]].rotateLeft(); + } + } + } + root.set(BLACK); + } + + // From CLR + void fixAfterDeletion() { + Box x = this; + while (x != root && color(x) == BLACK) { + if (x == left(parent[x])) { + Box sib = right(parent[x]); + if (color(sib) == RED) { + setColor(sib, BLACK); + setColor(parent[x], RED); + parent[x].rotateLeft(); + sib = right(parent[x]); + } + if (color(left(sib)) == BLACK && color(right(sib)) == BLACK) { + setColor(sib, RED); + x = parent[x]; + } + else { + if (color(right(sib)) == BLACK) { + setColor(left(sib), BLACK); + setColor(sib, RED); + sib.rotateRight(); + sib = right(parent[x]); + } + setColor(sib, color(parent[x])); + setColor(parent[x], BLACK); + setColor(right(sib), BLACK); + parent[x].rotateLeft(); + x = root; + } + } + else { + Box sib = left(parent[x]); + if (color(sib) == RED) { + setColor(sib, BLACK); + setColor(parent[x], RED); + parent[x].rotateRight(); + sib = left(parent[x]); + } + if (color(right(sib)) == BLACK && color(left(sib)) == BLACK) { + setColor(sib, RED); + x = parent[x]; + } + else { + if (color(left(sib)) == BLACK) { + setColor(right(sib), BLACK); + setColor(sib, RED); + sib.rotateLeft(); + sib = left(parent[x]); + } + setColor(sib, color(parent[x])); + setColor(parent[x], BLACK); + setColor(left(sib), BLACK); + parent[x].rotateRight(); + x = root; + } + } + } + setColor(x, BLACK); + } + */ +}