CS61B - Lec 23 - Red-Black Trees


这门课变得越来越抽象了。上课不带着实现结构了,只能课下去做lab咯。

上节课讲的B-Tree好是好,但是很难实现。这节课要讲的是同时兼顾BST的结构以及B-Tree的平衡特性的红黑树。

Tree Rotation

定义树的旋转操作。
在这里插入图片描述
将节点G向左旋转,意思就是把G的右节点P变成G的父节点,G就成为了P的左子节点。原本P的左子节点k变成了G的右节点。可知旋转某个节点,总是将该节点下移一层。旋转是构造红黑树很重要的一步。

Red-Black Trees

首先,尝试着将2-3 Tree改造成BST。
在这里插入图片描述
对于一个节点有两个值的2-3 Tree,该怎么处理该节点呢?可以直接将该节点分开:
在这里插入图片描述
然而这样做的问题是,存在非树叶的节点,只有一个child。数据量大了肯定会造成不平衡。
在这里插入图片描述
第二种方法,把该节点左边的值,变成该节点的左子节点,然后用一道红线代表这种操作。对于每个2-3 Tree,都可以通过它变成一个标准的BST,这就是红黑树。注意红线只是一个标记,(为了之后的构造操作)并没有什么特别的,红黑树仍然是BST。
综上,可以得到由2-3 Tree改造的红黑树的两条性质:

  1. 不存在有两条红线的节点。这是因为如果有两条红线,2-3 Tree的该节点数据数量就超过2,不符合规则。
  2. 所有无子节点的节点到顶部(根部)的路径,包含的黑线数量都是相同的。这是因为2-3 Tree是平衡的,底部所有节点到顶部的高度都是相同的,而红黑树的黑线就是原本2-3 Tree的连线。

下面就要构造红黑树。通过2-3 Tree构造?肯定不行,那样就绕了个圈子。接下来就要用到之前讲的旋转操作。

构造Red-Black Tree

构造红黑树时,一定要牢记以上两条性质,做的任何操作都不能破坏它们。
并且,任意一个红黑树,总是对应着一个B-Tree,所以对照着B-Tree的构造,进行相应的红黑树构造操作。

首先,插入每个节点时,用什么颜色连接呢?
在这里插入图片描述
答案是用红色。因为这样和B-Tree的操作相同。红线就代表B-Tree中的一节点多值。

下一个问题:之前定义了红线是>的关系,如果插入的节点值大于当前节点,那不就插到右边去了?
在这里插入图片描述
这里就需要旋转操作。比如S插在了E的右边,那么就rotateLeft(E),关系就正确了。

再看一种特殊情况:如果一个节点左右子节点都是用红线连接的,这代表2-3 Tree中的暂时超过L的节点,下一步就要将S放到父节点。这种暂时违反红线只能在左的规则是被允许的,之后再讲怎么处理。
在这里插入图片描述
但是当连续在左边插入两个节点时,连续两条红线,同样对应着这代表2-3 Tree中的暂时超过L的节点,但不是正确的形式。
在这里插入图片描述
同样,还是向右需要旋转Z,变成左右两条红线的格式。
在这里插入图片描述
变成左右两条红线后,只需除掉两条红线,再把与父节点的连线变成红线即可,如下图操作。同样还是与2-3 Tree相对应。
在这里插入图片描述
这就是构造红黑树所有需要的操作,就三个函数rotateLift, rotateRight, flip。
总结一下:

  • 插入新节点时,用红线连接
  • 如果红线在右,就需要rotateLeft
  • 如果有两条连续的红线,就rotateRight,变成两条红线一左一右的形式
  • 如果有两条红线,那就flip三个节点的颜色

至于Runtime,是和B-Tree相同的。Delete方法很难。

Java中的TreeMap就是用的与2-3-4 Tree对应的红黑树。

发布了20 篇原创文章 · 获赞 0 · 访问量 170

猜你喜欢

转载自blog.csdn.net/fourier_transformer/article/details/105466286