上回说到, avl 树的插入 -> 我们可以发现avl 树为了保持平衡 多次进行旋转, 其实很费时 -> avl很适合进行数据直接的查找, 但不适合插入太多的数据
so 我们讲解一下红黑树 我猜应该很多人很好奇这棵树 (比如我, 最开始接触 Java 某个类 底层是红黑树 我就很好奇了)
红黑树 也是 二叉搜索树, 接近平衡(最长路径不超过最短路径二倍), 新增加一个存储位来放置颜色(红色, 黑色), 一个节点是红色的它的两个孩子节点就要是黑色的(无2个连续的红色节点), 每一条简单路径上的黑色节点数相同
红黑树的插入
最开始形如搜索二叉树 之后调整颜色
最开始的节点初始设置色为红色 -> 如果是黑色(每一条简单路径上的黑色节点数相同) 你需要继续插入节点 但是红色->去调整颜色
谈论下调整颜色的情况 parent == grandFather.left
另一个else这个情况的条件则是相反 parent == grandFather.right
public class RBTree {
static class RBTreeNode{
public RBTreeNode left;
public RBTreeNode right;
public RBTreeNode parent;
public int val;
public COLOR color;
public RBTreeNode(int val){
this.val = val;
// 默认红色 不然新增为黑色 有求路径黑色节点数目相同 设置红色这个到时候可以调颜色
this.color = COLOR.RED;
}
}
public RBTreeNode root;
public boolean insert(int val){
RBTreeNode node = new RBTreeNode(val);
if(root==null){
root = node;
root.color = COLOR.BLACK;
return true;
}
RBTreeNode parent = null;
RBTreeNode cur = root;
while (cur != null){
if (cur.val > val){
parent = cur;
cur = cur.left;
} else if(cur.val == val){
return false;
} else {
parent = cur;
cur = cur.right;
}
}
if(val>parent.val){
parent.right = node;
node.parent = parent;
} else {
parent.left = node;
node.parent = parent;
}
cur = node;
// 调整
while (parent!= null && parent.color==COLOR.RED){
RBTreeNode grandFather = parent.parent;
if(parent == grandFather.left){
RBTreeNode uncle = grandFather.right;
if (uncle!=null && uncle.color==COLOR.RED){
parent.color=COLOR.BLACK;
uncle.color=COLOR.BLACK;
grandFather.color=COLOR.RED;
cur = grandFather;
parent = cur.parent;
} else {
if(cur==parent.right){
rotateLeft(parent);
RBTreeNode swap = cur;
cur = parent;
parent = swap;
}
rotateRight(grandFather);
parent.color = COLOR.BLACK;
grandFather.color = COLOR.RED;
}
} else {
RBTreeNode uncle = grandFather.left;
if (uncle!=null && uncle.color==COLOR.RED){
parent.color=COLOR.BLACK;
uncle.color=COLOR.BLACK;
grandFather.color=COLOR.RED;
cur = grandFather;
parent = cur.parent;
} else {
if(cur==parent.left){
rotateRight(parent);
RBTreeNode swap = cur;
cur = parent;
parent = swap;
}
rotateLeft(grandFather);
parent.color = COLOR.BLACK;
grandFather.color = COLOR.RED;
}
}
}
root.color = COLOR.BLACK;
return true;
}
private void rotateRight(RBTreeNode parent) {
RBTreeNode subL = parent.left;
RBTreeNode subLR = subL.right;
parent.left = subLR;
subL.right = parent;
if(subLR!=null) {
subLR.parent = parent;
}
RBTreeNode pParent = parent.parent;
parent.parent = subL;
// 看是不是根节点
if(parent == root){
root = subL;
root.parent = null;
} else {
// 不是根节点 看是左子树还是右子树
if(parent == pParent.left){
pParent.left = subL;
} else {
pParent.right = subL;
}
subL.parent = pParent;
}
}
private void rotateLeft(RBTreeNode parent) {
RBTreeNode subR = parent.right;
RBTreeNode subRL = subR.left;
subR.left = parent;
parent.right = subRL;
if(subRL!=null){
subRL.parent = parent;
}
RBTreeNode pParent = parent.parent;
parent.parent = subR;
if(parent==root){
root=subR;
root.parent = null;
} else {
if(pParent.left==parent){
pParent.left = subR;
} else {
pParent.right = subR;
}
subR.parent = pParent;
}
}
}
public enum COLOR {
RED,BLACK
}
okkk 所以红黑树 不用那么辛苦的维护平衡 有的时候只需要左旋/右旋~~~