Java实现红黑树

参考了算法导论,没有设置标兵作为外部节点,所以主要注意下空指针情况,红黑树的删除算法是真的吊

package qiuzhao;

public class RBTree<T extends Comparable<T>> {
	private static final boolean red = true;
	private static final boolean black = false;

	private RBNode<T> root;

	class RBNode<T extends Comparable<T>> {

		private T key;
		private boolean color;
		private RBNode<T> left;
		private RBNode<T> right;
		private RBNode<T> parent;

		public RBNode(T key, boolean color, RBNode<T> left, RBNode<T> right, RBNode<T> parent) {
			super();
			this.key = key;
			this.color = color;
			this.left = left;
			this.right = right;
			this.parent = parent;
		}

		public T getKey() {
			return key;
		}

		public void setKey(T key) {
			this.key = key;
		}

		public boolean isColor() {
			return color;
		}

		public void setColor(boolean color) {
			this.color = color;
		}

		public RBNode<T> getLeft() {
			return left;
		}

		public void setLeft(RBNode<T> left) {
			this.left = left;
		}

		public RBNode<T> getRight() {
			return right;
		}

		public void setRight(RBNode<T> right) {
			this.right = right;
		}

		public RBNode<T> getParent() {
			return parent;
		}

		public void setParent(RBNode<T> parent) {
			this.parent = parent;
		}

	}

	public void insert(T key) {
		RBNode<T> node = new RBNode<T>(key, black, null, null, null);

		// 如果新建结点失败,则返回。
		if (node != null)
			insert(node);
	}

	public void delete(T key) {
		RBNode<T> node;

		if ((node = search(root, key)) != null)
			delete(node);
	}

	private RBNode<T> search(RBNode<T> x, T key) {
		if (x == null)
			return x;

		int cmp = key.compareTo(x.key);
		if (cmp < 0)
			return search(x.left, key);
		else if (cmp > 0)
			return search(x.right, key);
		else
			return x;
	}

	private void print(RBNode<T> tree, T key, int direction) {

		if (tree != null) {

			if (direction == 0) // tree是根节点
				System.out.printf("%2d(B) is root\n", tree.key);
			else // tree是分支节点
				System.out.printf("%2d(%s) is %2d's %6s child\n", tree.key, tree.color == red ? "R" : "B", key,
						direction == 1 ? "right" : "left");

			print(tree.left, tree.key, -1);
			print(tree.right, tree.key, 1);
		}
	}

	public void print() {
		if (root != null)
			print(root, root.key, 0);
	}

	public void leftRotate(RBNode<T> x) {
		RBNode<T> y = x.right;
		x.right = y.left;
		if (y.left != null) {
			y.left.parent = x;
		}
		y.parent = x.parent;
		if (x.parent == null)
			this.root = y;
		else {
			if (x == x.parent.left)
				x.parent.left = y;
			else
				x.parent.right = y;
		}
		y.left = x;
		x.parent = y;
	}

	public void rightRotate(RBNode<T> y) {
		RBNode<T> x = y.left;
		y.left = x.right;
		if (x.right != null)
			x.right.parent = y;
		x.parent = y.parent;
		if (y.parent == null)
			this.root = x;
		if (y == y.parent.left)
			y.parent.left = x;
		else
			y.parent.right = x;
		y.parent = x;
		x.right = y;
	}

	public void insert(RBNode<T> z) {
		int cmp = 0;
		RBNode<T> pre = null;
		RBNode<T> p = this.root;
		while (p != null) {
			pre = p;
			cmp = p.key.compareTo(z.key);
			if (cmp < 0)
				p = p.right;
			else
				p = p.left;
		}
		z.parent = pre;
		if (pre != null) {
			cmp = pre.key.compareTo(z.key);
			if (cmp < 0)
				pre.right = z;
			else
				pre.left = z;
		} else
			this.root = z;
		z.color = red;
		insertFixUp(z);
	}

	private void insertFixUp(RBTree<T>.RBNode<T> z) {
		
		/*
		 * 循环不变式:
		 * 1、结点z一定是红色的
		 * 2、如果z.p是根节点,则z.p是黑色的
		 * 3、如果有任何红黑性质被破坏,则最对只有一条被破坏,或是性质2,或是性质4,如果性质2被破坏,其原因为z是根节点且是红结点;
		 * 如果性质4被破坏,其原因为z和z.p都是红色的。
		 */
		
		while (z.parent != null && z.parent.color == red) {
			if ( z.parent == z.parent.parent.left) {//z.p.p一定不为空
				RBNode<T> uncle = z.parent.parent.right;
				if (uncle != null && uncle.color == red) {//uncle是红色的
					z.parent.color = black;
					uncle.color = black;
					z.parent.parent.color = red;
					z = z.parent.parent;
				} else {
					if (z == z.parent.right) {//uncle是黑色的,并且z是右孩子
						z = z.parent;
						leftRotate(z);
					} else {//uncle是黑色的,并且z是左孩子
						z.parent.color = black;
						z.parent.parent.color = red;
						rightRotate(z.parent.parent);
					}
				}
			} else if (z.parent == z.parent.parent.right) {
				RBNode<T> uncle = z.parent.parent.left;
				if (uncle != null && uncle.color == red) {
					z.parent.color = black;
					uncle.color = black;
					z.parent.parent.color = red;
					z = z.parent.parent;
				} else {
					if (z == z.parent.left) {
						z = z.parent;
						rightRotate(z);
					} else {
						z.parent.color = black;
						z.parent.parent.color = red;
						leftRotate(z.parent.parent);
					}
				}
			}
		}
		this.root.color = black;
	}

	private void transplant(RBNode<T> u, RBNode<T> v) {
		if (u.parent == null)
			root = v;
		else if (u == u.parent.left)
			u.parent.left = v;
		else
			u.parent.right = v;
		if (v != null)
			v.parent = u.parent;
	}

	private RBNode<T> minimum(RBNode<T> x) {
		while (x != null && x.left != null) {
			x = x.left;
		}
		return x;
	}

	private RBNode<T> maximum(RBNode<T> x) {
		while (x != null && x.right != null) {
			x = x.right;
		}
		return x;
	}

	public void delete(RBNode<T> z) {
		RBNode<T> y = z;
		boolean y_o_color = y.color;
		RBNode<T> x = null;
		if (z.left == null) {
			x = z.right;
			transplant(z, z.right);
		} else if (z.right == null) {
			x = z.left;
			transplant(z, z.left);
		} else {
			y = minimum(z.right);
			y_o_color = y.color;
			x = y.right;
//			if (y.parent == z)
//				x.parent = y;
//			else {
			if(y.parent != z){
				transplant(y, y.right);
				y.right = z.right;
				y.right.parent = y;
			}
			transplant(z, y);
			y.left = z.left;
			z.left.parent = y;
			y.color = z.color;
		}
		if (y_o_color == black)
			delete_fixup(x);
	}

	private void delete_fixup(RBTree<T>.RBNode<T> x) {
		// TODO Auto-generated method stub
		while (x != root && x!= null && x.color == black) {
			if (x.parent != null && x == x.parent.left) {
				RBNode<T> bro = x.parent.right;
				if (bro != null && bro.color == red) {//bro为红色
					bro.color = black;
					x.parent.color = red;
					leftRotate(x.parent);
					bro = x.parent.right;
				}
				if ((bro.left == null || bro.left.color == black) && (bro.right == null || bro.right.color == black)) {
					//bro为黑色,而且bro的两个子结点为黑色
					bro.color = red;
					x = x.parent;
				} else {
					if (bro.right == null || bro.right.color == black) {//bro为黑色,bro左孩子为红色,bro右孩子为黑色
						bro.left.color = black;
						bro.color = red;
						rightRotate(bro);
						bro = x.parent.right;
					}
					//bro为黑色,bro右孩子为红色。
					bro.color = x.parent.color;
					x.parent.color = black;
					bro.right.color = black;
					leftRotate(x.parent);
					x = root;
				}
			} else if(x.parent != null && x == x.parent.right){
				RBNode<T> bro = x.parent.left;
				if (bro != null && bro.color == red) {
					bro.color = black;
					x.parent.color = red;
					rightRotate(x.parent);
					bro = x.parent.left;
				}
				if ((bro.right == null || bro.right.color == black) && (bro.left == null || bro.left.color == black)) {
					bro.color = red;
					x = x.parent;
				} else {
					if (bro.left == null || bro.left.color == black) {
						bro.right.color = black;
						bro.color = red;
						leftRotate(bro);
						bro = x.parent.left;
					}

					bro.color = x.parent.color;
					x.parent.color = black;
					bro.left.color = black;
					leftRotate(x.parent);
					x = root;
				}
			}
		}
		if (x != null)
			x.color = black;
	}

	public void inorderTra() {
		inorderTra(this.root);
	}

	private void inorderTra(RBNode<T> node) {
		if (node == null)
			return;
		inorderTra(node.left);
		System.out.println(node.key);
		inorderTra(node.right);
	}

}

package qiuzhao;

/**
 * Java 语言: 二叉查找树
 *
 * @author skywang
 * @date 2013/11/07
 */
public class RBTreeTest {

    private static final int a[] = {10, 40, 30, 60, 90, 70, 20, 50, 80};
    private static  boolean mDebugInsert = false;    // "插入"动作的检测开关(false,关闭;true,打开)
    private static  boolean mDebugDelete = false;    // "删除"动作的检测开关(false,关闭;true,打开)

    public static void main(String[] args) {
        int i, ilen = a.length;
        RBTree<Integer> tree=new RBTree<Integer>();

        System.out.printf("== 原始数据: ");
        for(i=0; i<ilen; i++)
            System.out.printf("%d ", a[i]);
        System.out.printf("\n");

        mDebugInsert=true;
        for(i=0; i<ilen; i++) {
            tree.insert(a[i]);
            // 设置mDebugInsert=true,测试"添加函数"
            
            if (mDebugInsert) {
                System.out.printf("== 添加节点: %d\n", a[i]);
                System.out.printf("== 树的详细信息: \n");
                tree.print();
                System.out.printf("\n");
            }
        }


        System.out.printf("\n== 中序遍历: ");
        tree.inorderTra();
        System.out.printf("\n");


        // 设置mDebugDelete=true,测试"删除函数"
        mDebugDelete=true;
        if (mDebugDelete) {
            for(i=0; i<ilen; i++)
            {
                tree.delete(a[i]);

                System.out.printf("== 删除节点: %d\n", a[i]);
                System.out.printf("== 树的详细信息: \n");
                tree.print();
                System.out.printf("\n");
            }
        }

    }
}

参考链接:http://www.cnblogs.com/skywang12345/p/3624343.html

猜你喜欢

转载自blog.csdn.net/fatii/article/details/78146115