红黑树(Red-Black Tree)的学习记录
(算法导论第三版第13章)
红黑树是一种特殊的二叉搜索树,其中的每一个节点都会着一种颜色,红色或黑色,通过对某些性质的限定,可以保证二叉树是近似平衡的,即红黑树中没有一条路径会比其他路径长出2倍。
一棵红黑树应满足的性质:
1、 每个节点或是红色的,或是黑色的。
2、 根节点是黑色的。
3、 每个叶结点是黑色的。
4、 如果一个结点是红色的,则它的两个子结点都是黑色的。
5、 对每个结点,从该结点到其他所有后代叶结点的简单路径上,均包含相同数目的黑色结点。
红黑树和普通的二叉搜索树一样,也支持SEARCH、PREDECESSOR、SUCCESSOR、MINIMUM、MAXIMUM、INSERT和DELETE等基本动态集合操作,并且可以保证在最坏情况下基本集合操作的时间复杂度为Ο(lgn)。
红黑树的SEARCH、PREDECESSOR、SUCCESSOR、MINIMUM、MAXIMUM等操作与普通二叉搜索树中的操作步骤一样。INSERT和DELETE操作有区别,因为在插入结点和删除结点时,就算维护了二叉搜索树的相关性质,也可能还会破坏红黑树的相关性质,所以需要额外的维护操作。
旋转(ROTATION)
在维护红黑树的性质时,需要用到一种关键的操作,旋转(Rotation),且分为左旋和右旋。假设在某个结点x上进行左旋,y为x的右孩子,那么可以将该操作看成x-y顺势左倾的操作,此时y将在x的位置,x将成为y的左孩子,原本y的左孩子将成为x的右孩子(且认为所有的结点都不为空)。右旋是相应的镜像操作。
以下是一位网友在他的博客中给出的关于旋转操作的图示,很直观,相信看了这个图对于旋转操作的过程就很了解了。
旋转操作有一个特性,就是可以调节子树的树高。比如在上图的右旋中,在旋转操作过后,x的树高增加了1,而其他结点的树高都没变。
那么在红黑树中,可以通过旋转且重新对某些结点着色,而调节子树的黑高,达到维护红黑树性质的目的。
旋转操作能完成以上的功能,我认为是基于一个性质,就是通过旋转,可以将一颗二叉搜索树转变为任何一颗含有相同结点的二叉搜索树(练习13.2-4的证明)。
对于插入和删除操作,书中的解释非常详细。
就对自己学习中碰见的一些问题做以下记录:
1、 还是旋转操作的问题。虽然理解了书中的知识点,但感觉要是碰见其他变体的问题,可能不会想到用旋转操作去解决,因为对于旋转操作的引入过程完全不了解,对于旋转操作的工作机制也还不是很了解。
2、 在插入和删除操作中几种情况之间的转换刚开始学习的时候需要注意。
比如在插入操作中,总共有3中情况,但其中第二种情况和第三种情况并不是完全独立的,往往是对第二种情况进行变形成为第三种情况统一解决,所以在书中给出的伪代码中,所进行的情况判定中,是把第一种情况和后面两种情况划分成两种独立的情况先进行判定,如果不是第一种情况,那么假如第二种独立的情况中判定是否是第二种情况,如果是,转换成第三种情况,否则就按第三种情况进行操作。用代码表示就应该是:
If case 1
…….
Else
If case 2
Case 2 falls through case3
Processing case 3
在删除操作中,从情况3到情况4也存在这种相同的转换过程。这都利用了旋转操作可以将一棵树转换为另一棵树的性质。在RB-DELETE过程中还有一点就是关于x,x记录的是y的原始位置,因为在整个删除过程中,就是原本y处的红黑性质会发生改变,从而可能导致红黑树的性质发生变化。