--- /dev/null
+// 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);
+ }
+ */
+}