2003/11/21 03:38:09
authormegacz <megacz@xwt.org>
Fri, 30 Jan 2004 07:42:00 +0000 (07:42 +0000)
committermegacz <megacz@xwt.org>
Fri, 30 Jan 2004 07:42:00 +0000 (07:42 +0000)
darcs-hash:20040130074200-2ba56-0755fc06deaca54e420628edf3d16cb815c6d7a6.gz

src/org/xwt/util/RedBlackTree.java [new file with mode: 0644]

diff --git a/src/org/xwt/util/RedBlackTree.java b/src/org/xwt/util/RedBlackTree.java
new file mode 100644 (file)
index 0000000..c848f64
--- /dev/null
@@ -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);
+    }
+    */
+}