提到红黑树,你是不是头皮发麻,难搞哦😔,别害怕,我来教你分分钟学会他
我们先来看一下红黑树的定义:
红黑树:
1) 每个节点颜色属性非红即黑
2) 根节点颜色一定是黑色的;
3) 如果一个节点是红的,那么它的两儿子都是黑的;
4) 对于任意节点而言,其到叶子节点的每条路径都包含相同数目的黑色节点数;(因为所有叶子节点都会回到 nil 哨兵结点,故本文忽略哨兵结点)
根据上述定义,我们可以设置红黑树 node 属性
------------------------------------------------------------------------------------
node
1.private RBNode leftchild; 左孩子
2.private RBNode rightchild; 右孩子
3.private RBNode parent; 父结点
4.private ColorType color; 颜色属性
5.private int key; 关键字
红黑树 new 的结点颜色为红色。
关于代码中的head结点 ???
自设的一个头节点,方便根结点能顺利带入代码,不用重新判断,并且头节点的左右孩子结点保存的是整棵树的最值,从而能够快速得到最值
--------------------------------------------------------------------------------------
上述属性应该不用我多说了叭,说不多说,下边进入正题,往红黑树中添加节点,我们应该怎样高效的维护呢?
红黑树的添加需要做两件事情:维护节点颜色要求;维护二叉搜索树的特点,即key值 左<中<右
关于颜色的变换,呐我的妙招就是和他祖父节点的另一个孩子结点(也就是它的堂叔)结点颜色进行比较,来维护树的颜色要求
关于树的平衡旋转,介个和二叉搜索树中的旋转一样,有单旋和双旋两种可能。
为了方便大家阅读,我做成了两张图,供大家学习
我们来看一下代码,adjustTree代码,希望你能看着上边的图,自己搞一下啦,俗话说的好:师傅领进门,修行靠个人🤭
public boolean insertItem(int key){
RBNode par = head;
RBNode p = getRoot();
while( p != NIL && p.getKey() != key){
par = p;
//先找到父结点位置
p = key < p.getKey() ? p.getLeftchild(): p.getRightchild();
}
//如果插入的值存在,则返回false
if(p != null && p.getKey() == key)
return false;
p = new RBNode(key,par,RED);
//结点的维护
p.setLeftchild(NIL);
p.setRightchild(NIL);
if(par == head){
//根结点
head.setLeftchild(p);
head.setRightchild(p);
head.setParent(p);
}else {
//孩子结点
if (key < par.getKey()) {
par.setLeftchild(p);
//维护整棵树的最值
if (key < head.getLeftchild().getKey()) {
head.setLeftchild(p);
}
} else {
par.setRightchild(p);
//维护整棵树的最值
if (key > head.getRightchild().getKey()) {
head.setRightchild(p);
}
}
}
//调整树的颜色
adjustTree(p);
count++;
return true;
}
教你几个小妙招:
1.一个方法只做一个事
2.所有事情分步做,做到原子性(学编程的各位原子性不用我多解释了叭