红黑树
Posted 数据结构与算法那些事儿
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了红黑树相关的知识,希望对你有一定的参考价值。
前言
红黑树
红黑树是一种自平衡的二叉查找树,也就是说它也有类似平衡二叉树的特点,在看红黑树的时候,建议把我之前写过的一篇平衡二叉树的文章看完再看红黑树就会容易一些。
性质
红黑树的结点不是红色就是黑色;
根的结点为黑色;
所有的叶子结点都是黑色(这里的叶子结点是空结点);
每个红色的结点必须有两个黑色的子结点;
从任何一个结点到其叶子结点的所有简单路径都包含相同数目的黑色结点;
例子:
恢复红黑树的性质需要少量O(logn)的颜色变更和不超过三次的树旋转(插入为两次),其操作时间依旧为O(logn)。
红黑树的插入
首先,我们可以从5个性质可以推断得出:
性质1和性质3总是能够保持;
性质4只有在这些情况下才会触发:
增加红色结点;
将黑色结点重新绘制成红色结点;
旋转;
性质5只有在这些情况下才会触发:
增加黑色结点;
将红色结点重新绘制成黑色结点;
旋转
首先,按照BST的规则将结点插入,并且将该结点标记为红色(因为如果将其标记为黑色,某条路径下将会多出一个黑色结点,则会导致无法满足性质5,并且不容易进行调整)
插入包括下面几种情况:
插入到一个空的树,插入结点则为根结点,只需要将红色结点重新转染成黑色结点来满足性质2;
新结点的父结点为黑色,满足所有条件;
新结点的父结点为红色,因为性质2和性质4,所以树必然有祖父结点,则又包括以下的情况:
父亲结点和叔父结点均为红色,显然无法满足性质4,则将父亲结点和叔父结点绘制成黑色,祖父结点设置成红色,但是仍然无法满足情况,比如考虑到祖父结点可能是根结点,则无法满足性质2,或者祖父结点的父结点是红色的,则无法满足性质4,这时需要将祖父结点作为新的结点来看待进行各种情况的判断,涉及到对祖父结点的递归;
父亲结点为红色同时叔父结点为黑色或者从缺,这里又分为两种情况,新插入结点为父亲结点的左子结点和右子结点(假设其中父亲结点为祖父结点的左子结点),区别在于旋转的方向,显然,这棵树父亲结点既然为红色,那么其祖父结点则为黑色(性质4),不然无法满足前提。
新插入结点为父亲结点的左子结点,那么就构成了一个左左的情况,在之前平衡树中提到过,如果要将其进行平衡,则需要对父结点进行一次单右旋转,形成一个父亲结点为相对根结点,子结点和祖父结点为子结点的树,同时将父亲结点的红色改为黑色,祖父结点更改为红色,这下之前无法满足的性质4和性质5就满足了。
新插入结点为父亲结点的右子结点,那么就会构成一个左右的情况,在之前的平衡树也提到过要进行一次双旋转,先对新结点进行一次单左旋转,变成了左左的结构,再进行一次单右旋转,从而达到满足所有性质。
父亲结点是祖父结点的右结点,参考平衡树进行相应的操作,原理是一致的。
插入的实现
同样的,我们先看核心的操作,左旋和右旋;
左旋
右旋
在了解两个基本操作以后,再来看整体的插入操作(代码有点长,截成了两部分):
上面的代码只是父亲结点为祖父结点的左子结点的情况,当然还包括父亲结点为祖父结点的右子结点的情况,不过原理大致是相通的,可以参考平衡二叉树将涉及方向的操作反过来即可。
红黑树和平衡二叉树的区别
红黑树相较于平衡二叉树来说,牺牲了部分的平衡性来换取在插入/删除操作时少量的旋转操作,即使两者的时间复杂度是差不多的,这是因为平衡二叉树在每一次进行插入/删除的时候都需要进行旋转来保证其完美平衡,而红黑树则是降低了平衡的要求,并不要求左子树和右子树的高度差为1。
当你的需求中存在大量的搜索,并远远的高于插入和删除,那么推荐使用平衡二叉树,相反,使用红黑树。
最后提前祝大家端午节快乐。
下篇文章预告
红黑树(二)
以上是关于红黑树的主要内容,如果未能解决你的问题,请参考以下文章