红黑树原理及相关操作
之前因为红黑树较为复杂,一直没敢接触,这几天在看hashmap和treemap,因为treemap是通过红黑树实现的,因此下定决心研究下,先看的麻省理工学院的视频(http://open.163.com/movie/2010/12/9/J/M6UTT5U0I_M6V2TJ49J.html),里面讲解了红黑树(RBT)关于搜索时间复杂度(树的高度)和插入操作两部分,删除操作后面自己通过看博客了解的,内容较多,这里做一个总结,方便以后查看。
文章分为以下几部分:
- 红黑树的基础概念
- 红黑树的高度(搜索时间复杂度)证明
- 红黑树与AVL(平衡二叉搜索树)的对比
- 红黑树的操作:左旋(右旋)、重新上色
- 红黑树的节点插入
- 红黑树的节点删除
红黑树的基础概念
红黑树(Red Black Tree)是一种“特殊”的二叉搜索树,特殊之处在于每个节点还有颜色,要么是黑色,要么是红色。红黑树最基(zhong)础(yao)的五个特性:
1. 每个节点是红色或者白色
2. 根节点是黑色
3. 每个叶子节点是黑色(注意:这里的叶子节点是为Null的空节点)
4. 红节点的子节点必须是黑色(不能连续出现两个红色节点)
5. 从任一节点到其每个叶子节点的所有路径都包含相同数目的黑色节点(黑节点的数目称为黑高black-height)
注意:
1. 特性3中的叶子节点,是只为空(NIL或null)的节点。
2. 特性5,确保没有一条路径会比其他路径长出俩倍。因而,红黑树是相对是接*衡的二叉树。
这五个特性是一颗二叉搜索树为红黑树的充要条件。
红黑树的高度(搜索时间复杂度)证明
对于一棵包含n个节点(不包括为null的叶子节点)的红黑树,存在以下定理:
- 一棵含有n个节点的红黑树的高度至多为2log(n+1).
下面给出证明,证明来自麻省理工的公开课。公式编辑太麻烦,直接上图(字丑了点。。)。
由证明可知红黑树的高度不超过2*log(n+1),因此其搜索、插入、删除等操作的时间复杂度为O(logn)。
红黑树与AVL树(平衡二叉搜索树)的对比
AVL树是指自平衡二叉查 找树。在AVL树中任何节点的两个儿子子树的高度最大差别为一,所以它也被称为高度平衡树。查找、插入和删除在平均和最坏情况下都是O(log n)。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。
为什么一般使用红黑树作为平衡树的实现?在博客和某乎上大神都做了解释,这里对他们的解释整理总结下。从搜索和插入删除两个方面比较
搜索:
红黑树的查询性能略微逊色于AVL树,因为他比avl树会稍微不平衡最多一层,也就是说红黑树的查询性能只比相同内容的avl树最多多一次比较,但是,红黑树在插入和删除上完爆avl树
插入删除节点红黑是用非严格的平衡来换取增删节点时候旋转次数的降低,任何不平衡都会在三次旋转之内解决,而AVL是严格平衡树,因此在增加或者删除节点的时候,根据不同情况,旋转的次数比红黑树要多。所以红黑树的插入效率更高
- 如果插入一个node引起了树的不平衡,AVL和RB-Tree都是最多只需要2次旋转操作,即两者都是O(1);但是在删除node引起树的不平衡时,最坏情况下,AVL需要维护从被删node到root这条路径上所有node的平衡性,因此需要旋转的量级O(logN),而RB-Tree最多只需3次旋转,只需要O(1)的复杂度。
- 其次,AVL的结构相较RB-Tree来说更为平衡,在插入和删除node更容易引起Tree的unbalance,因此在大量数据需要插入或者删除时,AVL需要rebalance的频率会更高。因此,RB-Tree在需要大量插入和删除node的场景下,效率更高。自然,由于AVL高度平衡,因此AVL的search效率更高。
总结: 红黑树并不追求“完全平衡”——它只要求部分地达到平衡要求,降低了对旋转的要求,从而提高了性能。
应用场景:java中Treemap和Treeset的实现,以及Linux虚拟内存的管理,都是通过红黑树去实现的。
红黑树的操作:左旋(右旋)、重新上色
重新上色:改变节点颜色(红变黑,黑变红)
左旋:将节点X左旋,等于将其变为右孩子的左节点。
具体例子如下:
右旋:将节点X右旋,等于将其变为左孩子的右节点。
具体例子如下:
注意:在红黑树种,当两个节点颜色冲突时,将位于上方的节点进行左旋或者右旋。
红黑树节点插入
节点插入可能会使得红黑树产生颜色冲突(连续有两个红色节点),即违反条件4。通过重新着色和左右旋转进行调整,且最多进行两次旋转即可。
注意:插入节点颜色必须是红色。
然后分为五种情况:
- 插入节点是根节点,直接插入
- 插入节点父节点是黑色,直接插入
- 插入节点父节点是红色,这时又可以分为三种情况(以父节点是祖父节点左节点为例,父节点是祖父节点右孩子相似):
3.1 当前节点的父节点是红色,且当前节点的祖父节点的另一个子节点(叔叔节点)也是红色。策略:重新上色,调换祖父节点和其左右子节点的颜色
3.2 当前节点的父节点是红色,叔叔节点是黑色,且当前节点是其父节点的右孩子,策略:对父节点进行左旋转,然后转入情况3
3.3 当前节点的父节点是红色,叔叔节点是黑色,且当前节点是其父节点的左孩子,策略:对父节点右旋转,此时达到平衡。
情况3如下如所示:
上图(a)部分对应3.1,(b)部分对应3.2,(c)部分对应3.3。因此最多只需要两次旋转即可达到平衡。
红黑树节点的删除
红黑树节点删除比较复杂,总结起来有点麻烦,网上很多都写得特别好,这里推荐一个:https://www.cnblogs.com/qingergege/p/7351659.html。