对与treeMap 这点我必须从二叉树 到 平衡树 到 红黑树讲解,比较麻烦,需要认真听下。
首先要了解二叉树,先了解树的概念
树
对于树来说,每个节点下面有多个节点,但一定会有个根节点,如上图的A
其中还有以下概念
就是孩子,兄弟。
层次来说就很简单,就像楼房一样
对于树的深度来说,就是像水平面开始,像下看,从根节点开始就是0,到最下面就是3
二叉树
对与二叉树,一句话来讲,就是度数最大为2,也就是孩子最多为2个节点的树
代码实现树的结构
其中还有个概念就是
满二叉树
满二叉树:满满的,都有2个子节点
完全二叉树
完全二叉树,最后的节点,要么有2个孩子,要么只有左孩子(前面节点都要有2个孩子)
二叉树搜索树
顾名思义,搜索二叉树是用来搜索的。关于前面二叉树的讲解,其实没必要看完,只需要了解只有2个度即可。
二叉搜索树结构很好理解。如图
就是左节点比父节点小,右节点比父节点大。
二叉树搜索树的添加
二叉搜索树的删除
对于有孩子情况的删除,需要拿后续节点替换。
对于后续节点的情况,如下图:
二叉搜索树搜索
如果找2的话只用搜索2次
得出结论,如果二叉树的平衡性好,那么搜索一个数最多次数为 n 的开根
为什么是开根呢?每一个深度的最多节点数量就是 2乘以 (深度个数)的2
那如果平衡性不好的呢?
哦,这就非常不好了,因为太不平衡了,这得遍历全部元素了。
平衡二叉树
从二叉搜索树不保障平衡性的缺点也已经可以看的出来了,要保障平衡,就要用到平衡二叉树
对于保持平衡二叉树的平衡,就涉及到左旋,右旋的概念了。
红黑树 And TreeMap演示
红黑树性质
1、每个结点或是红色的,或是黑色的
2、根节点是黑色的
3、每个叶结点(NIL)是黑色的
4、如果一个节点是红色的,则它的两个儿子都是黑色的。
5、对于每个结点,从该结点到其叶子结点构成的所有路径上的黑结点个数相同。
和AVL树的比较
AVL树是一棵严格的平衡树,它所有的子树都满足二叉平衡树的定义。因此AVL树高被严格控制在XXX,因此AVL树的查找比较高效。但AVL树插入、删除结点后旋转的次数比红黑树多。
红黑树用非严格的平衡来降低插入删除时旋转的次数。
因此,如果你的业务中查找远远多于插入、删除,那选AVL树;
如果查找、插入、删除频率差不多,那么选择红黑树。
这是网上复制过来了。接下来我来讲解每一个性质
在了解一下名词
我们来看下红黑树新增。
注意:叶子节点(nil)就是null,没有数,只要是末尾节点就有叶子节点,不管是红色还是黑色节点,都有空的叶子节点,在代码方面值要判断他的孩子是
null没有子节点,那么就当做叶子节点作为黑节点参与计算。
插入过程
默认插入的结点为红色。为何?
看下一个定律(5.从一个节点到叶子节点的黑色数目相同),如果你插入的是一个黑色,那么肯定打破这个性质。
- 父为黑
插入后无需任何操作。由于黑节点个数至少为红节点的两倍,因此父为黑的情况较多,而这种情况在插入后无需任何调整,这就是红黑树比AVL树插入效率高的原因! - 父为红
父为红的情况破坏了红黑树的性质(4、如果一个节点是红色的,则它的两个儿子都是黑色的),此时需要根据叔叔的颜色来做不同的处理。
叔叔为红
此时很简单,只需交换爸爸、叔叔和爷爷的颜色即可。
此时若爷爷节点和太爷爷节点颜色相同,再以爷爷节点为起始节点,进行刚才相同的操作,即:根据爷爷的兄弟颜色做相应的操作。(俗称回潮)
叔叔为黑 ,叔叔为黑,那么一定是叶子节点,也就是null,看(性质5:任意一结点到每个叶子结点的路径都包含数量相同的黑结点。)
此时较为复杂,分如下四种情况:
a)爸爸在左、叔叔在右、我在左
绕着祖先右旋
b)爸爸在左、叔叔在右、我在右
先以我为根节点,进行一次L旋转;
再以我为根节点,进行一次R旋转。
b)爸爸在左、叔叔在右、我在右
先以我为根节点,进行一次L旋转;
再以我为根节点,进行一次R旋转。
c)叔叔在左、爸爸在右、我在左
先以我为根节点,进行一次R旋转;
再以我为根节点,进行一次L旋转。
d)叔叔在左、爸爸在右、我在右
以爸爸为根节点,进行一次L旋转。
其TreeMap结构如下
对于新增的调整
删除过程
对于红黑树的删除,就跟之前讲解的二叉查找树的删除一样
本质就是找后续节点替换
1.删除的都是红色的
1.1 没有后续节点(没有孩子),并且是红色
这种直接删除
1.2 有后续节点,并且后续节点是红色
这种的话,后续节点替换父节点,并且颜色要继承过去 - 删除都是黑色(要删除的节点在左边,在右边相反即可)
- 直接删除的颜色是黑色
- 后续节点也是黑色
我们将这2种情况结合起来,按照叔叔颜色进行调整
请注意:我们为什么做成这个样子,接下请看下面的图。
看到这张图,您应该知道了吧,因为我们要统一当做s为黑色处理
SL右旋,在左旋,然后改成P的颜色,在把P改成黑色。
此时就SR是红色也是平衡,SR是黑色就是nil 叶子节点,也是平衡的。
这个图所白了,就是S为支点左旋,然后S继承P的颜色,P 和 SR颜色改成黑色。
此时DR是要被删除的,SL红色黑色都不影响。(SL黑色是nil别问为什么,看5个特征)
红黑树删除总结:
- 删除的都是红色
1.1 没有后续节点,直接删除
1.2 有后续节点,替换(包括颜色) - 删除的黑色(要删除的节点在左边)
2.1有后续节点,直接替换,包括颜色(此时删除的DR就是后续节点,因为替换的时候,并没有把替换的节点删除,他还残留着,用做调整),没有后续节点,把他当做后续节点来统一操作。
2.1.1 如果兄弟节点颜色为红色,那么兄弟的孩子节点一定是2个黑色,并且父亲肯定为红色。此时把兄弟节点左旋,并且颜色换成黑色,父亲颜色换成红色。此时就会变成下面的情况。
2.1.2 父亲为红色,兄弟为黑色。
2.1.2.1 兄弟的左孩子为红色,左孩子为支点右旋,颜色换成现在父节的颜色(红色),然后现在父亲的颜色换成黑色,在左旋(目前在现在父亲的右边,此时左旋换成老大)
2.1.2.2兄弟的右孩子为红色,直接兄弟继承父亲颜色,然后父亲换成黑色,兄弟在直接左旋。
2.1.2.3兄弟的两个孩子都为黑色,此时直接把兄弟换成红色,父亲改黑色
2.1.3 父亲为黑色,兄弟为黑色
同 2.1.2
TreeMap删除调整的源码: