Left_Leaning RedBlack Tree

Left-Leaning RedBlack Tree 是一种redblack tree 它总是喜欢把红节点放在左子树上
它符合红黑树的所有性质
(1) 所有的节点要么是红色的要么是黑色的
(2) 红色节点的子节点是黑色节点
(3) 叶子节点(NIL)节点是黑色的
(4) 一个节点到任意一个叶子节点路径上的所有的黑色节点的个数是想等的
(5) 根节点为黑色节点
redblacktree本身就是二叉平衡树的一种,它是从2-3-4tree进化而来的
首先介绍下2-3-4Tree 在2-3-4node 中只有3种节点 为以下三种
这里写图片描述
.首先介绍下2-3-4 tree的插入
在插入的过程中 如果节点是2node 则变成3node
3node则变成4node
4node则从中间开始分裂 中间的值加入父亲节点
整个树的增长过程如下图所示
树的增长过程
从增长的结构来看 2-3-4 tree无论怎么插入都保持着平衡的性质
也许我们可以来写一个这样的数据结构来存储对象 这样一来无论插入删除或者查找一个固定的对象 则可以在指数时间内完成!但是这个数据结构比较复杂
在整个树的增长过程中涉及到很多数的操作 比如说将2node变成3node
将3node变成4node 这些代码去实现的话都稍微复杂了!
然后就想到了另外一种数据结构Left-Leaning redblack tree
其实Left-Leaning redblack tree 和2-3-4tree中的node是一一对应的 。
这就相当于用Left-Leaning redblack tree 来表示了2-3-4tree ,因为2-3-4tree是平衡的所以 Left-Leaning redblack tree 也是平衡的 所以使用Left-Leaning redblack tree 可以在对数时间内找到对象 或者插入或者删除对象 下图显示了 2-3-4tree和Left-Leaning redblack tree 是如何一一对应的
这里写图片描述
这里写图片描述
在3node转化为Left-Leaning redblack tree中的节点时 应该是左倾的
也就是说在转化的过程中也只有第一种可能
也就是说是不可能出现以下情况的 在建树的时候 出现以下情况都会进行调整
最后变成符合要求的情况
这里写图片描述
在图中 红线链接的末端是代表着红色的节点, 在Left-Leaning redblack tree中用红色线段链接的说明在对应的2-3-4tree中是同一个node中的值。
下面介绍下Left-Leaning redblack tree中节点的插入
插入时每一个刚刚插入的节点都是红色的 下面的图片介绍了整个插入过程中需要的调整操作。
这里写图片描述
下面是插入的代码
这里写图片描述
记得在插入的过程中没插入完后都需要进行调整,以便保持
Left-Leaning redblack tree的性质!
下面再介绍下删除树中的元素 ,在介绍删除任意一个节点之前,先介绍怎样去删除树中的最大的或者最小的元素,因为在删除任意一个节点中会用到这些!
我们在删除的时候总是不想破坏树的平衡性,可是怎样才能不破坏树的平衡性呢! 因为Left-Leaning redblack tree和2-3-4tree是一一对应的所以也就是研究怎样在2-3-4tree中删除节点而不破坏2-3-4tree的平衡性。
最大最小值都在树的底部。如果要删除的值在3node或者4node 中则不会坏原来树的平衡性 因为3Node可以变成2node 4node可以变成3node .所以我们要把最后要删除的节点通过旋转或者 色彩的变换 放到一个3或者4node 中 而不是一个2node 因为删除一个2node 就会破坏原来树的平衡性

(1)首先介绍删除树中的最大值
在删除的过程中需要进行的调整如下图所示
这里写图片描述
下面我来解释下上图中所作的调整。
因为要删除最大的值,而最大的值一般在右子树上
(1.1)。来考虑原来的情况
一个根节点和一个左孩子 。在这种情况下最大的是根节点。删除根节点以后还得再调整左孩子的位置。但是如果将整个树右旋变成右倾的话 变成了一个根节点还有右孩子节点的问题。这样的话只要删除右孩子节点就可以了。这是讲原来只有左孩子右旋的原因。
(1.2)第二种情况 节点的右孩子节点还有右孩子节点的左孩子都是黑的则要按照如图所示的方法进行调整。 我想说下我对这个问题的理解
我们为什么要考虑当前节点的右孩子节点还有右孩子节点左孩子呢?因为只有他们全为黑色的时候 当前节点的右孩子节点在对应的2-3-4tree中是一个2-node 而2node 的删除会导致树失去原有的平衡性。所以要进行调整 。而调整的目的就是为了让当前节点的右子节点不是一个2node 而是一个3or4node
只要保证当前节点的右子节点不是2-node的话,然后不断的迭代下去最后一个最大值(在最右下角的位置)也一定不是一个2-node 这样进行删除的话就不会破坏原来的2-3-4tree中的平衡性。 至于为什么要在当前节点的右孩子节点还有右孩子节点左孩子都为黑色的情况下进行调整的话为什么考虑左孩子的左孩子节点的颜色呢?这是因为在调整过程中如果进行一次color的flip(就是将当前节点的颜色变成与原来相反的颜色 将左孩子还有右孩子也变成原来相反的颜色)之后如果原来的左孩子的左孩子节点也是红色的 则会产生红色节点的子节点还是红色的节点的现象 而这个是不符合redblack tree的性质的 所以要进行调整。
下面是删除最大值的代码
这里写图片描述
这里要修正下 图片中的h.left=deleteMax(h.left)改成 h.right=deleteMax(h.right) 因为最大总是在右子树中
还要解释下fixup()函数,fixup()函数是用来进行删除后的调整的。因为在删除的过程中调整了很多性质,例如将有红色左子树的进行右旋 ,这样就使得树
不符合 Left-Leaning RedBlack Tree将红色节点放到左子树的特点 下面的图片展示了整个调整的过程
这里写图片描述
在上面删除的过程中先进行递归搜索节点 在删除结束后返回的时候再进行调整!
(2)下面介绍删除树中最小值的情况
与删除最大值相对应在删除最小值得时候也得考虑进行调整使得最小值不在对应的2-3-4tree的2node中而是在3 or 4node中,下图展示了这个调整的过程
这里写图片描述
其实整个调整的目的就是为了让最小值不在2node 中,这样进行删除的时候就不会破坏原来树的平衡性。我说下我对这个过程的理解 ,首先程序判断的是当前节点的左孩子 还有左孩子的左孩子节点是不是都是黑色的。因为只要当前节点的左孩子节点或者左孩子节点的左孩子节点有一个不是黑色那么就说明了:当前节点的左孩子节点在对应的2-3-4tree中不是一个2node 而如果左孩子节点和左孩子节点的左孩子节点都是黑色的话则会导致左孩子节点是一个2node 则要进行调整。只要我们保证当前节点的左孩子节点不在一个2Node中那么进行递归搜索后 最小值也一定不在一个2node中。也许有人会想为什么在moveRedLeft的过程中要考虑 h.right.left的颜色进行不同的调整呢?主要是在一次color flip()后如果h.right.left为红色的话 则会导致h.right和h.right.left都为红 而这种情况是不允许出现的。下面的图片展示了删除最小值的过程。
这里写图片描述
(3)介绍删除任意一个元素的情况
在删除的时候我们得考虑两种情况
(3.1)在叶子节点上 ,这种情况直接删除就行了
(3.2)不在叶子节点上,这种情况删除原来的节点后,还要用后继的节点放在原来删除的位置上,这个后继节点可以是 左子树中的最大值,也可以是右子树中的最小值。而且在整个删除的过程中我们也要确保要删除的节点对应于2-3-4tree所在位置不是一个2node ,这样在左子树中删除的时候就需要判断当左孩子节点是一个2node的时候就要调用moveRedLeft()函数, 在右子树中删除的时候当右孩子节点在一个2node中的时候就要调用moveRedRight()函数使得右孩子节点在一个3or4node中
这里写图片描述
最后写一点llrb tree的优点 就是在随机插入n个元素后 整个树的平均查找长度为logn 而在最坏的情况下查找路径的长度为2logn。而在STL中 map multimap set multiset 都是使用RB tree来实现的。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值