1.紅黑樹首先是一顆二叉搜索樹
2.每一個節點要麼爲紅色,要麼爲黑色
3.根節點爲黑色
4.每條路徑的黑色節點數相同
5.每條路徑中不能有兩個連續的紅色節點node
每次插入的節點初始化爲紅色
插入情形總共分爲如下幾種狀況
1.插入節點父節點爲黑色
在這種狀況中,由於插入節點爲紅色,因此不會影響此紅黑樹的結構,直接插入便可
2.插入節點父節點爲紅色
在此種狀況中插入會破壞紅黑樹的平衡,必須進行自平衡操做,主要是旋轉操做,首先咱們對一些概念就行解釋bash
2.1插入節點的叔叔節點爲紅色
ide
2.2.1插入節點的父節點爲祖父節點的左子節點
性能
2.2.1.1插入節點爲父節點的左子節點
ui
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;
}
}
複製代碼
爲何有了AVL樹還要紅黑樹?
紅黑樹不追求"徹底平衡",即不像AVL要求節點的高度差<=1,它只要求部分達到平衡,可是提出了爲節點增長顏色,紅黑是用非嚴格的平衡來換取增刪節點時候旋轉次數的下降,而AVL是嚴格平衡樹,所以在增長或者刪除節點的時候,根據不一樣狀況,旋轉的次數比紅黑樹要多。
可是紅黑樹的搜索性能要遜於AVL,由於AVL是徹底平衡的,紅黑樹要比AVL最多多一層。
this
最後刪除操做我還沒學會。spa