红黑树的插入操作

315 阅读3分钟

1.红黑树定义

1.红黑树首先是一颗二叉搜索树
2.每个节点要么为红色,要么为黑色
3.根节点为黑色
4.每条路径的黑色节点数相同
5.每条路径中不能有两个连续的红色节点

2.红黑树的插入过程

(1)插入情形分析

每次插入的节点初始化为红色
插入情形总共分为以下几种情况
1.插入节点父节点为黑色
在这种情况中,因为插入节点为红色,所以不会影响此红黑树的结构,直接插入即可
2.插入节点父节点为红色
在此种情况中插入会破坏红黑树的平衡,必须进行自平衡操作,主要是旋转操作,首先我们对一些概念就行解释

概念

旋转操作

2.1插入节点的叔叔节点为红色

2.1
2.2插入节点的叔叔节点为黑色或null

2.2.1插入节点的父节点为祖父节点的左子节点

2.2.1.1插入节点为父节点的左子节点

2.2.1.1

2.2.1.2插入节点为父节点的右子节点

2.2.1.2

2.2.2插入节点的父节点为祖父节点的右子节点
2.2.2.1插入节点为父节点的右子节点

2.2.2.1

2.2.2.2插入节点为父节点的左子节点

2.2.2.1

(2)插入代码

public class RBNode {
	RBNode left;
	RBNode right;
	RBNode parent;
	String color;
	int val;
	public RBNode(int val) {
		this.val=val;
		this.color="R";
	}
	//插入节点
	public void insert(RBNode node) {
		if(node.val<this.val) {
			if(this.left==null) {
				this.left=node;
				node.parent=this;
				//插入之后调用自平衡方法进行平衡
				fixed3(node);
			}else {
				this.left.insert(node);
			}
		}
		if(node.val>this.val) {
			if(this.right==null) {
				this.right=node;
				node.parent=this;
				//插入之后调用自平衡方法进行平衡
				fixed3(node);
			}else {
				this.right.insert(node);
			}
		}
	}
	public void fixed3(RBNode node) {
		if(node==null) return;
		//如果节点为根节点则变为黑色;
		if(node.parent==null) {
			node.color="B";
			return;
		}
		//如果父节点为黑色则不处理,父节点为红色则必须进行处理才能保持平衡,父节点为红色时,祖父节点必然存在,因为不能有两个连续的红色节点
		if(node.parent.color=="R") {
			//1.父节点和叔节点都为红色
			if(node.parent.parent.left!=null&&node.parent.parent.right!=null&&node.parent.parent.left.color=="R"&&node.parent.parent.right.color=="R") {
				node.parent.parent.left.color="B";
				node.parent.parent.right.color="B";
				node.parent.parent.color="R";
				fixed3(node.parent.parent);
				return;
			}
			//2.叔叔节点为黑色或不存在
			//2.1 插入节点的父节点为祖父节点的左节点
			if(node.parent.equals(node.parent.parent.left)&&(node.parent.parent.right==null||node.parent.parent.right.color=="B")) {
				//2.1.1 插入节点为父节点的左节点
				if(node.equals(node.parent.left)) {
					node.parent.color="B";
					node.parent.parent.color="R";
					node.parent.parent.rightRotate();
					return;
				}
				//2.1.2 插入节点为父节点的右节点
				if(node.equals(node.parent.right)) {
					node = node.parent;
					node.leftRotate();
					fixed3(node.left);
					return;
				}
			}
			//2.2 插入节点的父节点为祖父节点的右节点
			if(node.parent.equals(node.parent.parent.right)&&(node.parent.parent.left==null||node.parent.parent.left.color=="B")) {
				//2.2.1 插入节点为父节点的左节点
				if(node.equals(node.parent.left)) {
					node = node.parent;
					node.rightRotate();
					fixed3(node.right);
					return;
				}
				//2.2.2 插入节点为父节点的右节点
				if(node.equals(node.parent.right)) {
					node.parent.color="B";
					node.parent.parent.color="R";
					node.parent.parent.leftRotate();
					return;
				}
			}
		}
	}
	//左旋转操作
	public void leftRotate() {
		RBNode newNode = new RBNode(this.val);
		newNode.left=this.left;
		newNode.right=this.right.left;
		if(newNode.left!=null) {
			newNode.left.parent=newNode;
		}
		if(newNode.right!=null) {
			newNode.right.parent=newNode;			
		}
		newNode.color=this.color;
		this.val=this.right.val;
		this.color=this.right.color;
		this.left=newNode;
		this.right=this.right.right;
		if(this.left!=null) {
			this.left.parent=this;
		}
		if(this.right!=null) {
			this.right.parent=this;			
		}
	}
	//右旋转操作
	public void rightRotate() {
		RBNode newNode = new RBNode(val);
		newNode.color=this.color;
		newNode.right=this.right;
		newNode.left=this.left.right;
		if(newNode.left!=null) {			
			newNode.left.parent=newNode;
		}
		if(newNode.right!=null) {
			newNode.right.parent=newNode;
		}
		this.val=this.left.val;
		this.color=this.left.color;
		this.left=this.left.left;
		this.right=newNode;
		if(this.left!=null) {
			this.left.parent=this;			
		}
		if(this.right!=null) {
			this.right.parent=this;
		}
	}

	//前序遍历
	public void frontShow() {
		System.out.println(this.color+" "+this.val);
		if(this.left!=null) {
			this.left.frontShow();
		}
		if(this.right!=null) {
			this.right.frontShow();
		}
	}
	//重写equals判断节点是否相等
	@Override
	public boolean equals(Object obj) {
		if((RBNode)obj==null) {
			return false;
		}
		if(this.val==((RBNode)obj).val) {
			return true;
		}
		return false;
	}
}

3.一些思考?

为什么有了AVL树还要红黑树?
红黑树不追求"完全平衡",即不像AVL要求节点的高度差<=1,它只要求部分达到平衡,但是提出了为节点增加颜色,红黑是用非严格的平衡来换取增删节点时候旋转次数的降低,而AVL是严格平衡树,因此在增加或者删除节点的时候,根据不同情况,旋转的次数比红黑树要多。
但是红黑树的搜索性能要逊于AVL,因为AVL是完全平衡的,红黑树要比AVL最多多一层。

最后删除操作我还没学会。