紅黑樹的插入操做

1.紅黑樹定義

1.紅黑樹首先是一顆二叉搜索樹
2.每一個節點要麼爲紅色,要麼爲黑色
3.根節點爲黑色
4.每條路徑的黑色節點數相同
5.每條路徑中不能有兩個連續的紅色節點node

2.紅黑樹的插入過程

(1)插入情形分析

每次插入的節點初始化爲紅色
插入情形總共分爲如下幾種狀況
1.插入節點父節點爲黑色
在這種狀況中,由於插入節點爲紅色,因此不會影響此紅黑樹的結構,直接插入便可
2.插入節點父節點爲紅色
在此種狀況中插入會破壞紅黑樹的平衡,必須進行自平衡操做,主要是旋轉操做,首先咱們對一些概念就行解釋bash

概念

旋轉操做

2.1插入節點的叔叔節點爲紅色
ide

2.1
2.2插入節點的叔叔節點爲黑色或null

2.2.1插入節點的父節點爲祖父節點的左子節點
性能

2.2.1.1插入節點爲父節點的左子節點
ui

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最多多一層。
this

最後刪除操做我還沒學會。spa

相關文章
相關標籤/搜索