算法导论笔记:13-01红黑树概念与基本操作

       因二叉搜索树的字典操作的时间复杂度都是O(h),所以,当二叉搜索树的高度较小时,可以获得较快的执行。只有当二叉搜索树变得“平衡”时,高度才会达到最低。

       红黑树是许多“平衡”搜索树中的一种,可以保证在最坏情况下基本动态集合操作的时间为O(lg n)

 

一:概念与性质

       红黑树是一种二叉搜索树,同时它又具有其他的性质。红黑树的结点具有颜色属性,分别为RED或者BLACK。通过对每条分支上的结点颜色做约束,可以保证没有一条路径会比其他路径长2倍,所以红黑树近似于平衡。

 

       红黑树的结点具有5个属性:color, key, left, right, p。红黑树的性质是:

a:每个结点或者是红色,或者是黑色;

b:根节点是黑色的;

c:叶节点(见附注)是黑色的;

d:如果一个结点是红色的,则它的两个子节点都是黑色的;

e:每个结点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色结点。

 

       下图就是一个红黑树:

 

       附注:为了便于处理边界条件,使用一个哨兵T.nil来处理所有NULL的情况,它的color属性为BLACK,其他属性可以为任意值。原红黑树中,所有指向NULL的情况都指向T.nil,所以,上述性质中的“叶节点是黑色的”,指的是哨兵T.nil是黑色的。有了哨兵之后,上面的红黑树就如下图:

       有了哨兵结点之后,我们一般关注内部结点,他们才是原红黑树真正的结点,所以一般不再画出哨兵结点:

 

二:红黑树的高度

       因为从某个结点到叶节点所有路径上的黑结点数都是相同的。所以:从某个结点x出发(不包括该节点),到达一个叶节点的任意一条路径上,黑色结点的个数成为该节点的黑高,记为bh(x)

 

       一个具有n个内部结点的红黑树,高度最多为2lg(n+1)

证明:

       可以先证明x为根的子树,最少包含 个内部结点。使用数学归纳法证明:

       如果x的黑高为0,则x为叶节点(T.nil),所以bh(x) = 0,内部结点数为  = 0。

       如果x有两个子节点,则子节点的黑高为bh(x)或者bh(x)-1,具体的取值取决于子节点本身的颜色。所以,每个子节点至少包含 个内部节点,所以,x为根的子树至少包含2*( )+ 1个内部节点,也就是 。因而得证。

       如果树的高度为h,根据红黑树的性质,从根到叶节点的任何一个简单路径上,黑结点的个数至少占到一半,所以根的黑高至少为h/2。所以bh(x) >= h/2。所以:n       。所以:h  2lg(n+1)。

 

三:旋转

       红黑树的插入和删除操作会改变红黑树的性质,所以为了保持红黑树的性质,需要改变结点的颜色或者指针结构。

 

       红黑树的旋转就是其中的一种操作,旋转操作能够保持红黑树的二叉搜索树性质。有两种旋转,左旋和右旋,如下图:

左旋代码如下:

       LEFT-ROTATE(T, x)                                                 

              y = x.right                  // set y                                              

              x.right = y.left           // turn y’s left subtree into x’sright subtree

              if y.left != T.nil                                                

                     y.left.p = x                                                      

                    

              y.p = x.p                    // link x’s parent to y                                 

              if x.p == T.nil                                                   

                     T.root = y                                                        

              else if x == x.p. left                                             

                     x.p. left = y                                                      

             else x.p.right = y   

                                           

             y.left= x                    // put x on y’sleft                                 

             x.p= y   

 

       右旋操作的代码是对称的,如下,左旋和右旋都可以在O(1)时间内完成。                                                      

       RIGHT-ROTATE(T, x)                                                 

              y = x.left                    // set y                                              

              x.left = y.right           // turn y’s right subtree into x’s leftsubtree

              if y.right ≠ T.nil                                                

                     y.right.p = x                                                      

                    

              y.p = x.p                    // link x’s parent to y                                

              if x.p == T.nil                                                    

                     T.root = y                                                        

              elseif x == x.p. right                                             

                     x.p. right = y                                                     

             elsex.p.left = y   

                                           

             y.right= x                  // put x on y’sright                                 

             x.p= y



原文地址:https://www.cnblogs.com/gqtcgq/p/7247234.html