数据结构
jdk1.7时数据结构如下:
由于冲突的元素过多链表过长时会导致查询速度会变慢,所以jdk1.8时增加了红黑树数据结构,在链表过长的时候会将链表装化为红黑树。
红黑树
特征
(1)根节点为黑色
(2)红色节点的两个子节点一定是黑色
(3)默认添加的节点是红色节点
(4)每个节点到叶子节点的所有路径黑色节点数相同
(5)所有叶子节点都为黑色节点
添加变换规则
总的变换规则
- 改变节点颜色
- 左旋&&右旋
变色规则:
父亲叔叔都为红色,则
(1)父亲叔叔都变为黑色
(2)祖父变红
(3)指针指向到祖父节点
旋转规则:
左旋:
父亲为红色 叔叔为黑色或者为空,当前节点为右子树,
以祖父节点为中心旋转
右旋:
父亲为红色 叔叔为黑色或者为空,当前节点为左子树,
(1)将父亲变为黑色,
(2)将祖父变为红色
(3)以祖父节点为中心旋转
总结一下就是:将红色变为黑色,将黑色变为红色:红色上移。
示例:
有了上面的变换规则,我们根据上面的规则,对节点进行调整就可以了。
1.在红黑树中我们添加了节点21,默认添加的节点都是红色;
2.在插入红色节点21后违背了规则2,根据变色规则将父亲叔叔节点都变为黑色,再将祖父节点变为红色。
3.这时候红黑树满足规则不需要再做调整,然后插入新的节点18;
4.添加节点后满足右旋规则,父亲节点为红色,叔叔节点为空,当前节点为左子树,所以需要先变色后右旋。
将父亲节点变为红色,再将祖父节点变为黑色:
5.然后以祖父节点为旋转中心进行右旋(顺时针旋转),将22的左子树进行旋转。旋转后22的左子树21作为父亲节点,22作为右节点,此时树的高度降低达到平衡状态。
6.最后满足红黑树规则,树节点最后如下:
删除变换规则
红黑树的删除节点跟添加节点一样,比较复杂,删除节点也会让树不符合红黑树的特性,也需要解决这些冲突。
删除操作分为2个步骤:
将红黑树当作一颗二叉查找树,将节点删除
通过”旋转和重新着色”等一系列来修正该树,使之重新成为一棵红黑树
步骤1的删除操作可分为几种情况:
删除节点没有儿子:直接删除该节点
删除节点有1个儿子:删除该节点,并用该节点的儿子节点顶替它的位置
删除节点有2个儿子:可以转成成删除节点只有1个儿子的情况,跟二叉查找树一样,找出节点的右子树的最小元素(或者左子树的最大元素,这种节点称为后继节点),并把它的值转移到删除节点,然后删除这个后继节点。这个后继节点最多只有1个子节点(如果有2个子节点,说明还能找出右子树更小的值),所以这样删除2个儿子的节点就演变成了删除没有儿子的节点和删除只有1个儿子的节点的情况
删除节点之后要考虑的问题就是红黑树失衡的调整问题。
步骤2遇到的调整问题只有2种情况:
删除节点没有儿子节点
删除节点只有1个儿子节点
删除节点没有儿子节点的话,直接把节点删除即可。如果节点是黑色节点,需要进行平衡性调整,否则,不用调整平衡性。这里的平衡性调整跟删除只有1个儿子节点一样,删除只有1个儿子的调整会先把节点删除,然后儿子节点顶上来,顶上来之后再进行平衡性调整。而删除没有儿子节点的节点的话,先进行调整,调整之后再把这个节点删除。他们的调整策略是一样的,只不过没有儿子节点的情况下先进行调整,然后再删除节点,而有儿子节点的情况下,先把节点删除,删除之后儿子节点顶上来,然后再做平衡性调整。
删除节点只有1个儿子节点还分几种情况:
- 如果被删除的节点是红色节点,那说明它的父节点是黑色节点,儿子节点也是黑色节点,那么删除这个节点就不会影响红黑树的属性,直接使用它的黑色子节点代替它即可
- 如果被删除的节点是黑色节点,而它的儿子节点是红色节点。删除这个黑色节点之后,它的红色儿子节点顶替之后,会破坏性质5,只需要把儿子节点重绘为黑色节点即可,这样原先通过黑色删除节点的所有路径被现在的重绘后的儿子节点所代替
- 如果被删除的节点是黑色节点,而它的儿子节点也是黑色节点。这是一种复杂的情况,因为路径路过被删除节点的黑色节点路径少了1个,导致违反了性质5,所以需要对红黑树进行平衡调整。