10. 平衡搜索树

Goal: get a search tree data structure that we can insert, delete and search in O(log n). That means we want a tree that's guaranteed to be O(log(n)) in height.
Examples:

  • AVL trees
  • 2-3 trees
  • 2-3-4 trees
  • B-trees
  • Red-black trees ------------------ today
  • Skip lists
  • Treaps

Red-black trees

BST data structure with an extra color field for each node satisfying Read-black properties.

  1. Every node is either red or black.
  2. The root & leaves (nil's) are black
  3. Every red node has a black parent.
  4. All simple paths from a node x to a descendant leaf of x have same #black nodes = black-height(x).

black-height(x) does not count x itself.

红黑树例子

The first thing we would do is to prove that these properties imply that the tree has to have height O(log(n)). 这样就可以保证搜索是在log(n) time 解决的了。

Then, the hard part will be to make sure these properties stay true if they initially held true. 也就是说,当我们insert或者delete的时候要在O(log(n))里完成对数据的修改,并保持这些properties.

Height of red-black tree:

Red-black tree with n keys has height h \leq 2lg(n+1) = O(lg(n))

Proof sketch

merge each read node into it's black parent 然后就得到 2-3-4 tree

2-3-4 tree

除了leaves之外,每个2-3-4 tree 的Node都有2个,3个或者4个子节点。
由于红黑树的第四个property 这个2-3-4 tree 的 all leaves have the same depth.

设原来红黑树的高为h,由红黑树转换成的2-3-4 tree的高为h'
n为红黑树中的internal node的数量
# leaves = n+1 (由于红黑树是一个binary tree 并且每个internal node有2个子节点 可用induction证)
in a 2-3-4 tree 2h' \leq # leaves \leq 4h'
2h' \leq n+1
h' \leq lg(n+1)
h \leq 2h'
h \leq 2lg(n+1)

Corollary

Queries(Search, Min, Max, Successor, Predecessor run in O(lg n))time in a red-black tree)

Updates

Insert & Delete

  • BST operation
  • color changes
  • restructuring of links via rotaions.
rotations

RB-Insert(x): 以在之前的红黑树insert数字15为例
首先是做一个tree insert. Insert 的时候选择红色。


tree insert

如果之前做tree insert的时候insert 到了一个黑色node的下面,就很舒服。然而如果不是的话,我们就打破了红黑树的第三条property。于是我们首先考虑使用这种方法,对上方的node重新上色。
设A,B为两个红色node,且A,B为唯一一对连起来的红色node,B为A的子节点,当A的同parente node 为红色时一般可使用这种方法。使用这种方法后可能消除问题,也可能导致问题向上传递。而且,当A的parent为root时应该不能使用这种方法处理。


上下层换颜色

在这种情况下,刚才那种方法不能用,我们考虑先使用right rotation(18)
rotate之后这个树更加不平衡了,但是不急,这不是我们最终的目的。
rotate之后我们得到的红黑树没有打破第四条property,这是因为进行rotate的两个节点都是红色的。


rotation

接下来我们使用left rotation(7)
由于7和10一黑一红,简单地rotate之后大破了第四条和第二条property。但是在rotation 完成之后将7和10的颜色换过来之后,我们可以得到一个符合4条标准的黑红树。这个黑红树看起来就非常平衡。
在这里也可以理解刚才为什么要先进行right rotation了。如果不进行right rotation,直接进行left rotation,18会变成root,10变成7的子节点。然后18和7换颜色之后,10和7就成了两个连在一起的一对。一定要让两个连着的红色node在同一侧然后再进行第二次rotate。


left rotate 并换颜色

这个例子看到这里我基本已经知道各种情况怎么做了,但对于一种情况有疑问,就是如果第一种办法可以一直用到顶端怎么处理。
看了书发现解决方法是,在最后,无论如何,都将root设为黑色。(即insert有可能使黑色node层数加一,合情合理。)

Insert 代码

具体代码在英文版算法导论的315,316 页。

delete 代码

因为delete部分是自己看书的所以暂时就没有例子了

RB-TRANSPLANT(T, u, v)
    if u.p = T.nil
        T.root = v
    elseif u == u.p.left
        u.p.left = v
    else u.p.right = v
    v.p = u.p

这个TRANSPLANT和之前普通的BST的TRANSPLANT有所不同。本来最后一行v.p = u.p之前是有一行if的。说是,如果v不是T.nil的话v.p = u.p。这样改的原因应该是,红黑树里面的nil不是不同的nil,是key value 为nil的记录了数个variable的object。

RB-DELETE(T, z)
    y = z
    y-original-color = y.color
    if z.left == T.nil
        x =  z.right
        RB-TRANSPLANT(T, z, z.left)
    elseif z.right == T.nil
        x = z.left
        RB-TRANSPLANT(T, z, z.right)
    else y = TREE-MINIMUM(z.right)
        y-original-color = y.color
        x = y.right
        if y.p == z
            x.p = y
        else RB-TRANSPLANT(T, y, y.right)
            y.right = z.right
            y.right.p = y
        RB-TRANSPLANT(T, z, y)
        y.left = z.left
        y.left.p = y
        y.color = z.color
    if y-original-color == BLACK
        RB- DELETE-FIXUP(T, x)

第一个if和elseif中先把需要删除的node左侧为空和右侧为空的情况讨论清楚了。但是其实存在问题。如果需要删除的node本为红色,那这样删除之后,我们依然可以得到一个符合4条规矩的红黑树。但是,如果我们删除的是一个黑色node,那property 4大概率被打破(如果删的不是root),property 3可能被打破(如果p为红,且子节点中带红),property 2可能被打破(如果删除root)。感觉最后修复起来,可以先按是不是root分类,但还是很复杂。
在这前两种情况下,y-original-color是需要删除的节点的初始颜色,x是顶替位置的节点。
在最后一个else里面,y-original-color是顶替位置的节点(右侧最小的节点)的初始颜色,x是y右侧的子节点。整个流程大致和tree-delete是一致的,只是x.p = y一行让我觉得是没有意义的。比较有意思的是最终顶替节点的颜色变成和原节点一致。也就是说,如果y本来的颜色是红色,根据property 4,y本来下面只能跟两个nil,这样一番操作之后,得到的是一个没有任何问题的红黑树。如果y本来是黑色,那右侧可以跟一个红色node(有可能打破3,一定会打破4,但是容易修复,只要把这个红色node最后变成黑色就好),也可以跟一个nil(这种情况一定且仅仅会打破4,不知道怎么修复)。

前两种情况(删除黑节点时):
如果删的是root,且顶替节点为红,只需将顶替节点变黑就好。如果顶替节点为黑,不用作任何改变。
如果删的不是root,且顶替节点为红,只需将顶替节点变黑就好。如果顶替节点为黑,顶替的一定是nil。等同说其中一条枝干缺了一个黑色node,不知道如何处理。
最后一种情况(删除黑节点时):
和前两种情况几乎一致,只是修改颜色的node变成了顶替y位置的节点。上面已经分析过了,同样也是有一种十分棘手的情况。

RB-DELETE-FIXUP(T, x)
    while x ≠ T.root and x.color == BLACK
        if x == x.p.left
            w = x.p.right
            if w.color == RED
                w.color = BLACK                                                //case 1
                x.p.color = RED                                                //case 1
                LEFT-ROTATE(T, x.p)                                            //case 1
                w = x.p.right                                                  //case 1
            if w.left.color == BLACK and w.right.color == BLACK
                w.color = RED                                                  //case 2
                x = x.p                                                        //case 2
            else 
                if w.right.color == BLACK
                    w.left.color = BLACK                                       //case 3
                    w.color = RED                                              //case 3
                    RIGHT-TOTATE(T, w)                                         //case 3
                    w = w.p.right                                              //case 3

                w.color = x.p.color                                            //case 4
                x.p.color = BLACK                                              //case 4
                w.right.color = BLACK                                          //case 4
                LEFT-ROTATE(T, x.p)                                            //case 4
                x = T.root                                                     //case 4
    else(same as then clause with "right" and "left" exchanged)
x.color = BLACK

在这个fixup里面没有把之前的两种情况分出来,而是将它看成一个问题解决了。其实也很有道理,因为出问题的总是左边为nil,用右边node顶替的地方。那要出一个general的解法,那一定是先看看有没有问题(被顶替位置不是root就一定有问题,是root的话也要分情况),有问题的话看看能不能靠换颜色解决,如果不能那要解决的问题就变成了以x为末枝的那一条少了一个黑色的node。

看过代码之后发现,没有问题的情况和有情况但简单换颜色能解决的情况不会进入while loop。十分简单的解决了。后面使用loop和4种case都是为了解决x为黑色(nil),且x这一条少了一个黑色node的问题。

4 cases

对想出红黑树的人表示服气。大方向好好想想也不是不能想到,但能在知道大方向的前提下找到一种切实可行的方法,实在是厉害。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容

  • 红黑树是平衡二叉查找树的一种。为了深入理解红黑树,我们需要从二叉查找树开始讲起。 BST 二叉查找树(Binary...
    kanehe阅读 1,371评论 0 8
  • R-B Tree简介 R-B Tree,全称是Red-Black Tree,又称为“红黑树”,它一种特殊的二叉查找...
    张晨辉Allen阅读 9,247评论 5 30
  • 1、红黑树介绍 红黑树又称R-B Tree,全称是Red-Black Tree,它是一种特殊的二叉查找树,红黑树的...
    文哥的学习日记阅读 9,861评论 1 35
  • 独行的旅途中,与陌生人一秒的眼神交接,一分钟的短暂谈话,一小时途中搭伴,可能都会成为自己成长中的难忘回忆。在自己的...
    懿冉臻阅读 943评论 1 6