红黑树的理解与使用

来源:互联网 发布:小米网络电视安装 编辑:程序博客网 时间:2024/05/17 08:26

what?

  • 红黑树是一种二叉查找树,每个结点上会增加一个存储位表示结点的颜色,可以是RED与BLACK。
  • 通过对任何一条从根到叶子的路径上各个结点的着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,因而是接近平衡的。
    红黑树的每个结点都有五个域:color、key、left、right和p。如果某结点没有一个子结点(叶子结点)或父结点(根结点),则相应的指针p域为值NIL。NIL视为指向二叉查找树的外结点(叶子)的指针,而把带关键字(key有值)的结点视为树的内结点。
  • 红黑树的性质:
    1)每个结点不是红的就是黑的
    2)根结点是黑的
    3)每个叶结点(NIL)是黑的
    4)如果一个结点是红的,则它的两个儿子都是黑的
    5)对每个结点,从该结点到其子孙结点的所有路径上包含相同个黑结点

why?

一棵高度为h的二叉查找树的操作:search、predecessor、successor、minimum、maximum、insert、delete的时间复杂度都是O(h)。而红黑树(red-black tree)是许多“平衡的”查找树中的一种,它能保证在最坏的情况下,基本的动态集合操作时间为O(lgn)。

how?

左旋

*************left-rotate(T,x)*****************y <- right[x]                   //x的右子树赋给y指针right[x] <- left[y]             //y的左子树赋给x的右指针if left[y]!=nil[T]              //如果y的左指针不指向空结点    then p[left[y]] <- x        //x结点赋值给y左子树的父亲指针p[y] <- p[x]                    //x的父亲赋值给y的父亲指针if p[x] = nil[T]                //如果x的父亲指针指向空结点    then root[T] <- y           //根结点指针指向y结点else if x = left[p[x]]          //如果x的父亲的左指针指向x结点(x是左子树)    then left[p[x]] <- y        //x的父亲的左指针指向y结点else right[p[x]] <- y           //如果x的父亲的右指针指向x结点(x是右子树),x的父亲的右指针指向y结点left[y] <- x                    //y的左指针指向x结点p[x] <- y                       //x的父亲指针指向y结点

右旋

*****************right_rotate(T,x)*****************y <- left[x]                //x的左子树赋值给y指针left[x] <- right[y]         //y的右子树赋值给x的左指针if right[y] != nil[T]      //如果y的右指针不指向空结点    then p[r[y]] <-x        //x结点赋值给y的右子树的父亲指针if p[x] = nil[T]            //如果x的父亲指针不指向空结点    then root[T] <- y       //y结点赋值给T的根指针else if r[p[x]] = x         //如果x的父亲的右指针指向x结点(x是右子树)    then r[p[x]] <- y       //y结点赋值给x的父亲的右指针else l[p[x]] <- y           //如果x的父亲的左指针指向x结点(x是左子树),y结点赋值给x的父亲的左指针right[y] <- x               //x赋值给y的右指针p[x] <- y                   //y赋值给x的父亲指针

插入

RB-INSERT(T,z)y <- nil[T]                 //空结点赋值给y指针x <- root[T]                //根结点赋值给x指针while x != nil[T]           //循环:x不指向空结点    do y <- x               //  x指向的结点赋值给y指针    if key[z] < key[x]      //  如果需要插入的值比x结点的值小        then x <- left[x]   //    x指向结点的左结点赋值给x指针        else x <- right[x]  //  否则x指向结点的右结点赋值给x指针p[z] <- y                   //y指向的结点赋值给z的父亲指针if y = nil[T]               //如果空结点赋值给y指针    then root[T] <- z       //  z结点赋值给根指针    else if key[z] < key[y] //  如果z结点值小于y指向的结点的值        then left[y] <- z   //    z结点赋值给y指向的结点的左指针        else right[y] <- z  //    z结点赋值给y指向的结点的右指针left[z] <- nil[T]           //空结点赋值给z结点的左指针right[z] <- nil[T]          //空结点赋值给z结点的右指针color[z] <- RED             //RED赋值给z结点的颜色指针RB-INSERT-FIXUP(T,z)        //插入修复x指针是为了找到

插入修复

RB-INSERT-FIXUP(T,z)while color[p[z]] = RED    do if p[z] = left[p[p[z]]]        then y <- right[p[p[z]]]        if color[y] = RED            then color[p[z]] <- BLACK                color[y] <- BLACK                color[p[p[z]]] <- RED                z <- p[p[z]]        else if z = right[p[z]]            then z <- p[z]            LEFT-ROTATE(T,z)        color[p[z]] <- BLACK        color[p[p[z]]] <- RED        RIGHT-ROTATE(T,p[p[z]])    else(same as then clause with "right" and "left" exchanged)color[root[T]] <- BLACK 

删除

RB-DELETE(T,z)if left[z] = nil[T] or right[z] = nil[T]    then y <- z    else y <- TREE-SUCESSOR(z)if left[y] != nil[T]    then x <- left[y]    else x <- right[y]p[x] <- p[y]if p[y] = nil[T]    then root[T] <- x    else if y = left[p[y]]        then left[p[y]] <- x        else right[p[y]] <- xif y != z    then key[z] <- key[y]               copy y‘s satellite data into zif color[y] = BLACK    then RB-DELETE-FIXUP(T,x)return y

删除修复

RB-DELETE-FIXUP(T,x)while x != root[T] and color[x] = BLACK    do if x = left[p[x]]        then w <- right[p[x]]            if color[w] = RED                then color[w] <- BLACK                    color[p[x]] <- RED                    LEFT-ROTATE(T,p[x])                    w <- right[p[x]]                if color[left[w]] = BLACK and color[right[w]] = BLACK                    then color[w] <- RED                    else if color[right[w]] = BLACK                        then color[left[w]] <- BLACK                            color[w] <- RED                            RIGHT-ROTATE(T,w)                            w <- right[p[x]]                        color[w] <- color[p[x]]                        color[p[x]] <- BLACK                        color[right[w]] <- BLACK                        LEFT-ROTATE(T,p[x])                        x <- root[T]                else(same as then clause with "right" and "left" exchanged)color[x] <- BLACK               

虽然这些伪代码看起来生硬、难嚼,但是根据我之前的两段注释,相信就会容易理解一点。因为最近工作忙,之后,我会慢慢更新操作的图解,以及c++的实现代码。

原创粉丝点击