红黑树

红黑树

红黑树介绍

红黑树是一种特殊的二叉查找树,为什么说红黑树特殊呢?因为红黑树既满足二叉查找树的特点,又满足以下5条性质。

  1. 红黑树的根节点是黑色的
  2. 红黑树的节点非黑即红,不能既是黑色又是白色
  3. 红色节点的只能有两个黑色的子节点
  4. 叶子节点值得是NiL,叶子节点是黑色的
  5. 任何一个节点到它所有的叶子节点的黑节点个数相同

特性5确保了 从根节点到叶子节点的最长路径不会超过最短路径的两倍。

原理部分具体参考该大神的博客
有点错误,但总体上还是正确的。

左旋代码:

private void leftRotate(RBTNode<T> x) {
		RBTNode<T> y = x.right;    //x.right可不可能为空,先假设不可能为空
		
		x.right = y.left;
		if(y.left != null)
			y.left.parent = x;
		
		y.parent = x.parent;
		
		if(x.parent == null)
			this.mRoot = y;
		else {
			if(x.parent.left == x) 
				x.parent.left = y;
			else 
				x.parent.right = y;
		}
		
		y.left = x;
		x.parent = y;
	}

右旋代码:

private void rightRotate(RBTNode<T> x) {
		RBTNode<T> y = x.left;
		
		x.left = y.right;
		
		if(y.right!= null)
			y.right.parent = x;
		
		y.parent = x.parent;
		if(x.parent == null)
			this.mRoot = y;
		else {
			if(x.parent.left == x)
				x.parent.left = y;
			else
				x.parent.right = y;
		}
		
		y.right = x;
		x.parent = y;
	}

插入代码:

public void insert(RBTNode<T> node) {
		int cmp;
		RBTNode x = this.mRoot;
		RBTNode y = null;
		
		while(x!=null) {
			y = x;
			cmp = x.key.compareTo(node.key);
			if(cmp >  0)
				x = x.left;
			else 
				x = x.right;
		}
		if(y != null) {
			node.parent = y;
			cmp = y.key.compareTo(node.key);
			if(cmp > 0)
				y.left = node;
			else
				y.right = node;
		}else
			this.mRoot = node;
		/*
		 * if(node.parent!=null) System.out.println("#" + node.parent.key + " " +
		 * node.key); else System.out.println("#" + node.key);
		 */
		node.color = RED;
		insertFixUp(node);
	}

插入修正:

public void insertFixUp(RBTNode<T> node) {
		RBTNode parent,gparent,uncle;
		
		//父节点不为空,并且是红色
		while((parent = parentOf(node))!=null && isRed(parent)) {
			//猜测无论如何不可能根节点为红还能访问他的parent
			gparent = parentOf(parent);
			if(parent == gparent.left) {
				//情况1
				uncle = gparent.right;
				if(uncle !=null && isRed(uncle)) {
					setBlack(parent);
					setBlack(uncle);
					setRed(gparent);
					node = gparent;
					continue;
				}
				//情况2 uncle为空 或者 黑 其实空也是黑节点
				if(node == parent.right) {
					leftRotate(parent);
					RBTNode<T> temp;
					temp = parent;
					parent = node;
					node = temp;
				}
				setBlack(parent);
				setRed(gparent);
				rightRotate(gparent);
			}else {
				uncle = gparent.left;
				//情况1   uncle为红色
				if(uncle!=null && isRed(uncle)) {
					setBlack(parent);
					setBlack(uncle);
					setRed(gparent);
					node = gparent;
					continue;
				}
				
				//情况2 uncle为空 或者 黑 其实空也是黑节点
				if(node == parent.left) {
					rightRotate(parent);
					RBTNode<T> temp;
					temp = parent;
					parent = node;
					node = temp;
				}
				setBlack(parent);
				setRed(gparent);
				leftRotate(gparent);
			}
		}
		//最终要把根节点设置成黑色
		setBlack(mRoot);
	}

删除节点代码:

public void remove(RBTNode<T> node) {
		RBTNode parent,child;
		boolean color ;
		//如果被删除节点的左右子树都不为空,那么就得找到其后继节点
		if((node.left!=null) && node.right!=null) {
			RBTNode<T> replace;
			
			//找他的后继节点
			replace = node.right;
			while(replace.left!=null)
				replace = replace.left;
			
			parent = parentOf(replace);
			child = replace.right;
			
			//如果删除的不是根节点
			if(node.parent != null) {
				if(node.parent.left == node)
					node.parent.left = replace;
				else
					node.parent.right = replace;
			}else
				this.mRoot = replace;
			
			if(parent == node) 
				parent = replace;
			else {
				parent.left = child;
				if(child!=null)
					child.parent = parent;
				
				replace.right = node.right;
				node.right.parent = replace;
				
			}
			replace.parent = node.parent;
			replace.left = node.left;
			node.left.parent = replace;
			color = replace.color;
			
			
			if(color == BLACK) {
				//调整删除
				removeFixUp(child,parent);
			}
			
			node = null;
			return ;
			
		}
		
		//只有左孩子 或者 右孩子  或者 没有
		if(node.left!=null)
			child = node.left;
		else
			child = node.right;
		
		parent = node.parent;
		
		if(child!=null) 
			child.parent = parent;
		
		if(parent!=null)
			if(parent.left == node)
				parent.left = child;
			else
				parent.right = child;
		else
			this.mRoot = child;
		
		color = node.color;
		node = null;
		
		if(color == BLACK)
			removeFixUp(child,parent);  //删除根几点parent可能为空
		
		//找到后继节点
		
	}

删除修正:

public void removeFixUp(RBTNode<T>node ,  RBTNode<T>parent) {
		//删除节点的孩子节点等于空或者是黑色的节点才需要条 而且还不等于根节点
		RBTNode<T> other;
		while((node == null || isBlack(node)) && (node!=this.mRoot)) {
			//如果他是左孩子节点
			if(parent.left == node) {
				other = parent.right;
				//如果兄弟节点是红色
				if(isRed(other)) {
					setBlack(other);
					setRed(parent);
					leftRotate(parent);
					other = parent.right;
				}
				//如果x的兄弟节点是黑色并且他的左孩子右孩子节点也都是黑色
				if((other.left == null || isBlack(other.left)) && (other.right == null || isBlack(other.right))) {
					setRed(other);
					node = parent;
					parent = parent.parent;
				}else {
					//右孩子节点是黑色,左孩子节点是红色
					if(other.right == null || isBlack(other.right)) {
						setBlack(other.left);
						setRed(other);
						rightRotate(other);
						node = parent.right;
					}
					//兄弟的右孩子节点是红色节点
					other.color = parent.color;
					setBlack(parent);
					setBlack(other.right);
					leftRotate(parent);
					node = this.mRoot;
					break;
				}
			}else {
				other = parent.left;
				if(isRed(other)) {
					setBlack(other);
					setRed(parent);
					rightRotate(parent);
					other = parent.left;
					
				}
				
				
				if((other.left == null || isBlack(other.left)) && (other.right == null || isBlack(other.right))) {
					setRed(other);
					node = parent;
					parent = parent.parent;
				}else {
					//左孩子节点是黑色节点,右孩子孩子节点是红色节点
					if(other.left == null || isBlack(other.left)) {
						setBlack(other.right);
						setRed(other);
						leftRotate(other);
						node = parent.left;
					}
					//兄弟的左孩子节点是红色节点
					other.color = parent.color;
					setBlack(parent);
					setBlack(other.left);
					rightRotate(parent);
					node = this.mRoot;
					break;
				}
			}
			
			
		}
		if(node!=null)
			setBlack(node);
	}

全部代码:


public class RBTree <T extends Comparable<T>>{   //T这个类型必须实现了Comparable的compareTo方法
	private RBTNode<T> mRoot;
	
	private static final boolean RED   = false;
    private static final boolean BLACK = true;
	public class RBTNode<T extends Comparable<T> >{
		boolean color ;
		T key;
		RBTNode<T> left;
		RBTNode<T> right;
		RBTNode<T> parent;
		public RBTNode(T key,boolean color,RBTNode<T> parent,RBTNode<T> left,RBTNode<T> right) {
			this.key = key;
			this.color = color;
			this.parent = parent;
			this.left = left;
			this.right = right;
		}
		
	}
	
	private void leftRotate(RBTNode<T> x) {
		RBTNode<T> y = x.right;    //x.right可不可能为空,先假设不可能为空
		
		x.right = y.left;
		if(y.left != null)
			y.left.parent = x;
		
		y.parent = x.parent;
		
		if(x.parent == null)
			this.mRoot = y;
		else {
			if(x.parent.left == x) 
				x.parent.left = y;
			else 
				x.parent.right = y;
		}
		
		y.left = x;
		x.parent = y;
	}
	private void rightRotate(RBTNode<T> x) {
		RBTNode<T> y = x.left;
		
		x.left = y.right;
		
		if(y.right!= null)
			y.right.parent = x;
		
		y.parent = x.parent;
		if(x.parent == null)
			this.mRoot = y;
		else {
			if(x.parent.left == x)
				x.parent.left = y;
			else
				x.parent.right = y;
		}
		
		y.right = x;
		x.parent = y;
	}
	
	public void insert(RBTNode<T> node) {
		int cmp;
		RBTNode x = this.mRoot;
		RBTNode y = null;
		
		while(x!=null) {
			y = x;
			cmp = x.key.compareTo(node.key);
			if(cmp >  0)
				x = x.left;
			else 
				x = x.right;
		}
		if(y != null) {
			node.parent = y;
			cmp = y.key.compareTo(node.key);
			if(cmp > 0)
				y.left = node;
			else
				y.right = node;
		}else
			this.mRoot = node;
		/*
		 * if(node.parent!=null) System.out.println("#" + node.parent.key + " " +
		 * node.key); else System.out.println("#" + node.key);
		 */
		node.color = RED;
		insertFixUp(node);
	}
	
	public void insert(T key) {
		RBTNode<T> node = new RBTNode<T>(key,BLACK,null,null,null);
		if(node!=null) {
			insert(node);
		}
	}
	public RBTNode<T> parentOf(RBTNode<T> node){
		return node.parent;
	}
	public boolean isRed(RBTNode<T> node) {
		if(!node.color) 
			return true;
		else 
			return false;
	}
	public boolean isBlack(RBTNode<T> node) {
		if(node.color) 
			return true;
		else
			return false;
	}
	public void setBlack(RBTNode<T> node) {
		node.color = BLACK;
	}
	public void setRed(RBTNode<T> node) {
		node.color = RED;
	}
	public void insertFixUp(RBTNode<T> node) {
		RBTNode parent,gparent,uncle;
		
		//父节点不为空,并且是红色
		while((parent = parentOf(node))!=null && isRed(parent)) {
			//猜测无论如何不可能根节点为红还能访问他的parent
			gparent = parentOf(parent);
			if(parent == gparent.left) {
				//情况1
				uncle = gparent.right;
				if(uncle !=null && isRed(uncle)) {
					setBlack(parent);
					setBlack(uncle);
					setRed(gparent);
					node = gparent;
					continue;
				}
				//情况2 uncle为空 或者 黑 其实空也是黑节点
				if(node == parent.right) {
					leftRotate(parent);
					RBTNode<T> temp;
					temp = parent;
					parent = node;
					node = temp;
				}
				setBlack(parent);
				setRed(gparent);
				rightRotate(gparent);
			}else {
				uncle = gparent.left;
				//情况1   uncle为红色
				if(uncle!=null && isRed(uncle)) {
					setBlack(parent);
					setBlack(uncle);
					setRed(gparent);
					node = gparent;
					continue;
				}
				
				//情况2 uncle为空 或者 黑 其实空也是黑节点
				if(node == parent.left) {
					rightRotate(parent);
					RBTNode<T> temp;
					temp = parent;
					parent = node;
					node = temp;
				}
				setBlack(parent);
				setRed(gparent);
				leftRotate(gparent);
			}
		}
		//最终要把根节点设置成黑色
		setBlack(mRoot);
	}
	
	private void preOrder(RBTNode<T> tree) {
		if(tree == null)
			return;
		System.out.print(tree.key + ":");
		System.out.println(tree.color == true?"black":"red");
		preOrder(tree.left);
		preOrder(tree.right);
	}
	public void preOrder() {
		preOrder(this.mRoot);
	}
	
	private void inOrder(RBTNode<T> tree) {
		if(tree == null)
			return;
		inOrder(tree.left);
		System.out.print(tree.key + " ");
		inOrder(tree.right);
	}
	public void inOrder() {
		inOrder(this.mRoot);
	}
	
	private void postOrder(RBTNode<T> tree) {
		if(tree == null)
			return;
		postOrder(tree.left);
		postOrder(tree.right);
		System.out.print(tree.key + " ");
	}
	public void postOrder() {
		postOrder(this.mRoot);
	}
	
	public void remove(RBTNode<T> node) {
		RBTNode parent,child;
		boolean color ;
		//如果被删除节点的左右子树都不为空,那么就得找到其后继节点
		if((node.left!=null) && node.right!=null) {
			RBTNode<T> replace;
			
			//找他的后继节点
			replace = node.right;
			while(replace.left!=null)
				replace = replace.left;
			
			parent = parentOf(replace);
			child = replace.right;
			
			//如果删除的不是根节点
			if(node.parent != null) {
				if(node.parent.left == node)
					node.parent.left = replace;
				else
					node.parent.right = replace;
			}else
				this.mRoot = replace;
			
			if(parent == node) 
				parent = replace;
			else {
				parent.left = child;
				if(child!=null)
					child.parent = parent;
				
				replace.right = node.right;
				node.right.parent = replace;
				
			}
			replace.parent = node.parent;
			replace.left = node.left;
			node.left.parent = replace;
			color = replace.color;
			
			
			if(color == BLACK) {
				//调整删除
				removeFixUp(child,parent);
			}
			
			node = null;
			return ;
			
		}
		
		//只有左孩子 或者 右孩子  或者 没有
		if(node.left!=null)
			child = node.left;
		else
			child = node.right;
		
		parent = node.parent;
		
		if(child!=null) 
			child.parent = parent;
		
		if(parent!=null)
			if(parent.left == node)
				parent.left = child;
			else
				parent.right = child;
		else
			this.mRoot = child;
		
		color = node.color;
		node = null;
		
		if(color == BLACK)
			removeFixUp(child,parent);  //删除根几点parent可能为空
		
		//找到后继节点
		
	}
	//查找值
	public RBTNode<T>  search(RBTNode<T> node,T key) {
		if(node == null)
			return node;
		int cmp;
		cmp = node.key.compareTo(key);
		
		if(cmp > 0)
			return search(node.left, key);
		else if(cmp<0)
			return search(node.right, key);
		else
			return node;
	}
	
	public void remove(T key) {
		RBTNode<T> node;
		if((node = search(mRoot,key))!=null) {
			remove(node);
		}
	}
	
	public void removeFixUp(RBTNode<T>node ,  RBTNode<T>parent) {
		//删除节点的孩子节点等于空或者是黑色的节点才需要条 而且还不等于根节点
		RBTNode<T> other;
		while((node == null || isBlack(node)) && (node!=this.mRoot)) {
			//如果他是左孩子节点
			if(parent.left == node) {
				other = parent.right;
				//如果兄弟节点是红色
				if(isRed(other)) {
					setBlack(other);
					setRed(parent);
					leftRotate(parent);
					other = parent.right;
				}
				//如果x的兄弟节点是黑色并且他的左孩子右孩子节点也都是黑色
				if((other.left == null || isBlack(other.left)) && (other.right == null || isBlack(other.right))) {
					setRed(other);
					node = parent;
					parent = parent.parent;
				}else {
					//右孩子节点是黑色,左孩子节点是红色
					if(other.right == null || isBlack(other.right)) {
						setBlack(other.left);
						setRed(other);
						rightRotate(other);
						node = parent.right;
					}
					//兄弟的右孩子节点是红色节点
					other.color = parent.color;
					setBlack(parent);
					setBlack(other.right);
					leftRotate(parent);
					node = this.mRoot;
					break;
				}
			}else {
				other = parent.left;
				if(isRed(other)) {
					setBlack(other);
					setRed(parent);
					rightRotate(parent);
					other = parent.left;
					
				}
				
				
				if((other.left == null || isBlack(other.left)) && (other.right == null || isBlack(other.right))) {
					setRed(other);
					node = parent;
					parent = parent.parent;
				}else {
					//左孩子节点是黑色节点,右孩子孩子节点是红色节点
					if(other.left == null || isBlack(other.left)) {
						setBlack(other.right);
						setRed(other);
						leftRotate(other);
						node = parent.left;
					}
					//兄弟的左孩子节点是红色节点
					other.color = parent.color;
					setBlack(parent);
					setBlack(other.left);
					rightRotate(parent);
					node = this.mRoot;
					break;
				}
			}
			
			
		}
		if(node!=null)
			setBlack(node);
	}
}

测试代码:


public class BRTreeTest {
	private static final int a[] = {10, 40, 30, 60, 90, 70, 20, 50, 80};
	public static void main(String[] args) {
		int len = a.length;
		RBTree<Integer> tree = new RBTree<Integer>();
		System.out.println("原数据");
		for(int i=0;i<len;i++) {
			System.out.print(a[i] + " ");
			if(i == len) System.out.print("\n");
		}
		
		
		
		for(int i=0;i<len;i++) {
			tree.insert(a[i]);
		}
		
		System.out.println();
		System.out.println("前序遍历================================");
		tree.preOrder();
		System.out.println();
		System.out.println("中序遍历================================");
		tree.inOrder();
		System.out.println();
		System.out.println("后序遍历================================");
		tree.postOrder();
		
		tree.remove(30);
		
		System.out.println();
		System.out.println("删除第一个节点的前序遍历================================");
		tree.preOrder();
		
		System.out.println();
		System.out.println("中序遍历================================");
		tree.inOrder();
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值