标签:rand 个数 添加 结合 图解 VID 二叉搜索树 parent 判断
红黑树除了符合二叉搜索树的基本规则外,还添加了以下特性:
红黑树的相对平衡
前面5条规则的约束确保了以下红黑树的关键特性:
为什么可以做到最长路径不超过最短路径的两倍呢?
插入一个新节点时,有可能树不再平衡,可以通过三种方式的变换使树保持平衡:
为了重新符合红黑树的规则,需要把红色节点变为黑色,或者把黑色节点变为红色;
插入的新节点通常都是红色节点:
当插入的节点为红色的时候,大多数情况不违反红黑树的任何规则;
红色节点虽然可能导致红红相连的情况,但是这种情况可以通过颜色调换和旋转来调整;
以节点X为根逆时针旋转二叉搜索树,使得父节点原来的位置被自己的右子节点替代,左子节点的位置被父节点替代;
详解:
如上图所示,左旋转之后:
除此之外,二叉搜索树左旋转之后仍为二叉搜索树:
以节点X为根顺时针旋转二叉搜索树,使得父节点原来的位置被自己的左子节点替代,右子节点的位置被父节点替代;
详解:
如上图所示,右旋转之后:
除此之外,二叉搜索树右旋转之后仍为二叉搜索树:
首先需要明确,在保证满足红黑树5条规则的情况下,新插入的节点必然是红色节点。
为了方便说明,规定以下四个节点:新插入节点为N(Node),N的父节点为P(Parent),P的兄弟节点为U(Uncle),U的父节点为G(Grandpa),如下图所示:
当插入的新节点N位于树的根上时,没有父节点。
这种情况下,只需要将红色节点变为黑色节点即可满足规则2 。
新界点N的父节点P为黑色节点,此时不需要任何变化。
此时既满足规则4也满足规则5。尽管新节点是红色的,但是新节点N有两个黑色节点NIL,所以通向它的路径上黑色节点的个数依然相等,因此满足规则5 。
节点P为红色,节点U也为红色,此时节点G必为黑色,即父红叔红祖黑。
在这种情况下需要:
即变为父黑叔黑祖红,如下图所示:
可能出现的问题:
节点P是红色节点,节点U是黑色节点,并且节点N为节点P的左子节点,此时节点G一定是黑色节点,即父红叔黑祖黑。
在这种情况下需要:
节点P是红色节点,节点U是黑色节点,并且节点N为节点P的右子节点,此时节点G一定是黑色节点,即父红叔黑祖黑。
在这种情况下需要:
接着可以按照情况4进行处理:
先变色:将N1节点的父节点P1变为黑色,将祖父节点G变为红色;
最后将节点N1和P1变换回来,完成节点N的插入,如图 f 所示;
在二叉树中依次插入节点:10,9,8,7,6,5,4,3,2,1 。
如果直接采用普通的二叉搜索树,节点全部插入后是这样的:
是一个严重的不平衡树,相当于一个链表,不能体现出二叉搜索树的高效率。而按照红黑树的五条规则插入节点就能最大程度保证搜索二叉树是一棵平衡树。以下为过程详解:为了方便解释省略了部分红黑树的叶子节点(NIL)
符合情况1:
符合情况2:
快速判断属于情况3还是情况4的方法:
从新插入的节点N出发,按图示箭头经过的四个节点,若为红红黑红3个红色节点则为情况3,若为红红黑黑两个红色节点则为情况4;
符合情况4:
符合情况3:
符合情况4:
符合情况3:
符合情况4:
第一次变换:符合情况3:
变换之后发现5和7为相连的两个红色节点,于是把以5为根的整个子树看成一个新插入的节点N1,再进行第二次变换。
第二次变换:符合情况4:
最后复原N1得到变换后的红黑树:
符合情况4:
第一次变换:符合情况3:
变换之后发现3和5为相连的两个红色节点,于是把以3为根的整个子树看成一个新插入的节点N1,再进行第二次变换。
第二次变换:符合情况3:
变换之后发现根节点7为红色不符合规则2,所以把以7为根节点的红黑树看成一个新插入的节点N2,再进行第三次变换。
第三次变换:符合情况1:
由此,完成了1~10节点的插入,虽然没有遇到情况5,不过情况5经过左旋转的操作便可转换为情况4,原理一样。如下图所示,将这棵红黑树的叶子节点NIL补全之后,经检验满足红黑树的五条规则,并且基本属于平衡树,效率较高。
红黑树的删除操作结合了复杂的二叉树的删除操作和复杂的红黑树的插入规则,整体来说难度非常大,篇幅较长,这里暂不进行探讨。
参考资料:JavaScript数据结构与算法
标签:rand 个数 添加 结合 图解 VID 二叉搜索树 parent 判断
原文地址:https://www.cnblogs.com/AhuntSun-blog/p/12458115.html