数据结构与算法-红黑树

平衡二叉查找树

    平衡二叉树中任意一个节点的左右子树的高度相差不能大于1

        完全二叉树、满二叉树都是平衡二叉树,但非完全二叉树也有可能是平衡二叉树

    平衡二叉查找树满足上面平衡二叉树的定义,还满足二叉查找树的特点

    平衡二叉查找树为了解决普通二叉查找树频繁插入、删除等动态更新导致时间复杂度退化    

    平衡二叉查找树中“平衡”: 

        “平衡”可以等价为性能不退化

        让整棵树左右子树高度比较“平衡”,相应的插入、删除、查找等操作的效率高一些

    如设计一个平衡二叉查找树,只要树高度不比logn大很多,尽管不符合定义仍然可以算合格

平衡二叉树 VS 非平衡二叉树

红黑树(Red-Black Tree)

    是一种不严格的平衡二叉查找树,属于最常用平衡二叉查找树

    满足红黑树前提条件

        所有节点只有黑色和红色

        根节点是黑色

        每个叶子节点都是黑色的空节点(NIL) (主要为了简化代码实现而设置)

            添加黑色的空叶子节点,可以在具体实现的时候公用一个空节点,不会太浪费空间

        任何相邻的节点都不能同时为红色

        每个节点从该节点到达其可达叶子节点的所有路径,都包含相同数目的黑色节点

    红黑树是“近似平衡”

        “平衡”可以等价为性能不退化,而“近似平衡”等价为性能不会退化的太严重

        二叉查找树操作的性能都跟树的高度成正比,极其平衡的二叉树高度大约为logn

    特点

        只要按照这些固定的调整规则来操作,就能将一个非平衡的红黑树调整成平衡

        左旋(rotate left): 围绕某个节点的左旋

        右旋(rotate right): 围绕某个节点的右旋

左旋 VS 右旋

        红黑树的插入、删除操作会破坏红黑树的平衡,如何调整平衡

        名词介绍

            叔叔节点: 父节点的兄弟节点,

            祖父节点: 父节点的父节点

            关注节点: 正在处理的节点

            前驱节点: 中序遍历的序列中,当前节点上一个节点

            后继节点: 中序遍历的序列中,当前节点下一个节点

        插入操作的平衡调整

            红黑树定义: 插入的节点必须是红色,而且树中新插入的节点都放在叶子节点上

            具体情况如下:

                如果插入节点的父节点是黑色,那不需要任何调整,它仍然满足红黑树的定义

                如果插入的节点是根节点,那直接改变它的颜色,把它变成黑色就可以了

                其他情况都会违背红黑树的定义,需要进行两种基础的操作: 左右旋转和改变颜色

            实现过程

                红黑树的平衡调整过程是一个迭代的过程,

                关注节点随着不停地迭代处理,而不断发生变化。最开始的关注节点是新插入的节点

                新节点插入后,如果红黑树的平衡被打破,一般会有下面三种情况 & 如何实现再平衡

                Case 1.如果关注节点是a,它的叔叔节点d是红色,依次执行

                    将关注节点a的父节点b、叔叔节点d的颜色都设置成黑色

                    将关注节点a的祖父节点c的颜色设置成红色

                    关注节点变成a的祖父节点c

                    跳到CASE 2 或 CASE 3

Case 1

                Case 2.如果关注节点是a,叔叔节点d是黑色,关注节点a是其父节点b的右子节点

                    关注节点变成节点a的父节点b;

                    围绕新的关注节点b左旋;

                    跳到 CASE 3

Case 2

                Case 3.如果关注节点是a,叔叔节点d是黑色,关注节点a是其父节点b的左子节点

                    围绕关注节点a的祖父节点c右旋;

                    将关注节点a的父节点b、兄弟节点c的颜色互换。

Case 3

        删除操作的平衡调整

            实现过程

                1.针对删除节点初步调整

                    红黑树定义中“只包含红色节点和黑色节点”,经过初步调整之后,

                    为了保证这一条要求,有些节点会被标记成两种颜色,“红-黑”或者“黑-黑”。

                    如果一个节点被标记为“黑-黑”,那在计算黑色节点个数的时候,要算成两个黑色节

                    如果一个节点既可以是红色,也可以是黑色,在下图用一半红色一半黑色来表示

                    如果一个节点是“红-黑”或者“黑-黑”,我会用左上⻆的一个小黑点来表示额外的黑色

                    Case 1:如果要删除的节点是a,它只有一个子节点b

                        删除节点a,并且把节点b替换到节点a的位置

                        节点a只能是黑色,节点b也只能是红色,不符合红黑树定义,把节点b改为黑色

Case 1

                Case 2:如果要删除的节点a有两个非空子节点,且后继节点是节点a的右子节点c

                    如果节点a后继节点是右子节点c,把节点a删除且将节点c替换到节点a的位置

                    然后把节点c的颜色设置为跟节点a相同的颜色

                    如果节点c是黑色,给节点c右子节点d多加一个黑色,则节点d变成“红-黑”或“黑-黑”

                    这时关注节点变成了节点d,第二步的调整操作就会针对关注节点d来做

Case 2

                    Case 3:如果要删除是节点a有两个非空子节点,且节点a后继节点不是右子节点

                        找到后继节点d,并将它删除,删除后继节点d的过程参照CASE 1

                        将节点a替换成后继节点d

                        把节点d的颜色设置为跟节点a相同的颜色

                        如果节点d是黑色,给节点d右子节c多加一个黑色,则节点c就成“红-黑”或“黑-黑”

                        这时关注节点变成节点c,第二步的调整操作就会针对关注节点c来做

Case 3

                2.针对关注节点进行二次调整

                    经过初步调整之后,关注节点变成“红-黑”或“黑-黑”节点

                    二次调整是为了让红黑树中不存在相邻的红色节点

                    针对这个关注节点,我们再分四种情况来进行二次调整

                    Case 1: 如果关注节点是a,它的兄弟节点c是红色的

                        围绕关注节点a的父节点b左旋

                        关注节点a的父节点b和祖父节点c交换颜色

                        关注节点不变

                        继续从四种情况中选择适合的规则来调整

Case 1

                    Case 2: 如果关注节点是a,兄弟节点c是黑色,且节点c左右子节点d、e都是黑色

                        将关注节点a的兄弟节点c的颜色变成红色

                        从关注节点a中去掉一个黑色,这个时候节点a就是单纯的红色或者黑色

                        给关注节点a的父节点b添加一个黑色,这时节点b就变成了“红-黑”或者“黑黑”

                        关注节点从a变成其父节点b

                        继续从四种情况中选择符合的规则来调整

Case 2

                    Case 3: 如果关注节点是a,兄弟节点c是黑色,c左子节点d红色,c右子节点e黑色

                        围绕关注节点a的兄弟节点c右旋

                        节点c和节点d交换颜色

                        关注节点不变跳转到Case 4,继续调整

                    Case 4: 如果关注节点a的兄弟节点c是黑色的,并且c的右子节点是红色的

                        围绕关注节点a的父节点b左旋

                        将关注节点a的兄弟节点c的颜色,跟关注节点a的父节点b设置成相同的颜色;

                        将关注节点a的父节点b的颜色设置为黑色;

                        从关注节点a中去掉一个黑色,节点a就变成了单纯的红色或者黑色;

                        将关注节点a的叔叔节点e设置为黑色;

                        调整结束。

Case 4

    总结操作过程

        第一点,把红黑树的平衡调整的过程比作魔方复原,不要过于深究这个算法的正确性

            只要按照固定的操作步骤,保持插入、删除的过程,不破坏平衡树的定义即可

        第二点,找准关注节点,不要搞丢、搞错关注节点

            每种操作规则,都是基于关注节点来做的

            在迭代的调整过程中,关注节点在不停地改变

        第三点,插入操作的平衡调整比较简单,但是删除操作就比较复杂

            针对删除操作,我们有两次调整,

            第一次针对要删除的节点做初步调整,让调整后的红黑树继续满足第四条定义

                “每个节点到可达叶子节点的路径都包含相同个数的黑色节点”

                但是不满足第三条定义,有可能会存在两个红色节点相邻的情况

            第二次调整就是解决让红黑树不存在相邻的红色节点的问题

    几种平衡二叉查找树对比

        Treap(树堆)

            Treap是二叉搜索树和堆合并构成的数据结构,每个节点数据域包含2个值

                key值: 满足左子树<根节点<右子树 (满足二叉搜索树特性)

                weight值:小于等于(或大于等于)左右子节点 (满足堆特性)

            利用weight值作为随机因子来调整二叉树形状,所以在大部分情况下更平衡,性能更高

            但无法避免极端情况下时间复杂度的退化,不适用对于操作时间非常敏感场景

        Splay Tree(伸展树)

            是一种能够自我平衡的二叉查找树

            每次查找后对树进行调整,把被查找的条目搬移到离根节点近一些的地方

            它会沿着从某个节点到根节点之间的路径,通过一系列的旋转把这个节点搬移到根节点

            良好的的性能,同时存储所需的内存少

            但无法避免极端情况下时间复杂度的退化(特别在多线程环境)            

        AVL树

            一种高度平衡的二叉树,查找的效率非常高; 

            但是AVL树为了维持高度的平衡,每次插入、删除等操作都要调整,就比较复杂、耗时; 

            对于有频繁的插入、删除操作的数据集合,使用AVL树的代价就有点高

        红黑树

            红黑树的插入、删除、查找等操作性能都比较稳定

            因近似平衡,在维护平衡的成本上,要比AVL树要低

        综合对比

            为了支撑这种工业级的应用,我们更倾向于这种性能稳定的平衡二叉查找树

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