数据结构学习笔记之红黑树

一. 定义
  红黑树和2-3树等价的,在理解了2-3树之后,再来看红黑树会比较容易理解。理解了2-3树不但对理解红黑树有帮助,还会对理解B树有帮助。

  1. 2-3 树

  2-3树是最简单的B-树结构,其每个非叶节点都有两个或三个子女,而且所有叶都在统一层上。2-3树不是二叉树,其节点可拥有3个孩子,不过,2-3树与满二叉树相似。高为h的2-3树包含的节点数大于等于高度为h的满二叉树的节点数,即至少有2^h-1个节点。

  2-3树是由二节点和三节点组成的,它是一个绝对平衡的树,它的特殊性质使得无论对该树做什么操作(添加节点或者删除节点),他都能保持树的绝对平衡(类似于满二叉树)。

2-3树

  2-3树也是一种搜索树(左子节点的值小于当前节点,右节点的值大于当前节点),在添加节点时,除了根节点之外,新节点是永远不会添加到一个空的位置的,也就是二节点只能通过分裂形成,所在在添加节点时,它实际上做了以下两步。
  (1)找寻合适的位置,融合到2-3树中的节点(已存在)中。
  (2)如果融合之后使得当前节点变成一个四节点,则分裂为一颗高度为 2 的树,然后将该树的头结点与父节点融合,重复(2) 直到融合后的节点不是四节点。

添加节点的过程
  1. 红黑树
      红黑树是一种自平衡的二叉查找树,它具有以下五条性质:
      (1)树中的节点要么是红色要么是黑色。
      (2)根节点是黑色的。
      (3)所有的叶子都是黑色(叶子是NULL节点)。
      (4)每个红色节点的两个孩子都是黑色的(红黑树中的任意一条路径不可能存在两个相连的红色节点)。
      (5)从任意节点到每个叶子节点的所有路径都包含相同数目的黑色节点。
红黑树
  1. 红黑树和 2-3 树的联系
      红黑树和2-3树之间实际上是等价的,联系如下:
红黑树和2-3树的联系

  知道了红黑树和2-3树之间的联系之后,我们再回过头来看红黑树的五个性质:
  (1)由于2-3 树是由2节点和3节点组成,根据上图中2节点和3节点与红黑树中节点的对应关系,我们可得出第一条性质。
  (2)对于红黑树中的根节点,其有可能是2-3树中的2节点和3节点,无论哪种表示其该节点都是黑色的,可得出第二条性质。
  (3)红黑树中的定义空节点为黑色的。
  (4)同样,红节点表示3节点左侧的节点,而2-3树的左侧节点无非连接的是2节点或者3节点,所以可以得出第四条性质。
  (5)因为2-3树是一种绝对平衡的,所以对于任意一个节点,其子节点的高度是一致的,所以经过的路径长度是一致的,由上图的转化关系可知,无论是2节点还是3节点转化成红黑树时都会有一个黑节点,所以对于红黑树中的黑节点也是绝对平衡的,所以得出第五条性质。
  红黑树是保持"黑平衡"的二叉树,严格意义来说不是平衡二叉树。

二. 基本使用
  向红黑树添加的新节点一定是红色的,因为红节点表示与父节点融合,所以当添加红节点时,树还会是平衡的。红黑树(左倾)添加节点比较复杂,包括六种情况,分别如下:
  (1)红黑树为空时,添加完节点之后,要把新添加的红节点着为黑色。
  (2)当添加的节点在黑节点的左侧时,此时相当于向 2-3 树的2节点融合新节点成为3节点,直接添加即可。

二节点左侧

  (3)当新添加的节点在黑节点的右侧时,根据2-3树的性质,红节点一定是左倾斜的,所以需要进行左旋,具体流程如下:

左旋
    private Node leftRotate(Node node){
        Node x = node.right;
        node.right = x.left;
        x.left = node;
        // 由于 x 节点要替换到原来 node 的位置,所以x的颜色要和node一致
        x.color = node.color;
        // 由于node节点要与 x 节点表示2-3 树的2节点, 所以描为红色
        node.color = Node.RED;
        return x;
    }

  (4)当新添加节点在2-3树3节点(红+黑)的右侧时(红+黑+红),会形成一个4节点,此时根据2-3树的性质要将该节点拆分为3个2节点,所以根据对应关系先将所有的节点着黑色,拆分成树之后根节点要和父节点融合,所以将根节点着红色。

颜色翻转
    private Node flipColors(Node node){
        node.color = Node.RED;

        node.left.color = Node.BLACK;
        node.right.color = Node.BLACK;
        return node;
    }

  (5)当新添加节点在3节点的左侧时,会形成(红+红+黑)的情况,所以将节点右旋,此时会转化成第四种情况(x节点:红黑红)。

红红黑
    private Node rightRotate(Node node){
        Node x = node.left;
        node.left = x.right;
        x.right = node;

        // 由于 x 节点要替换到原来 node 的位置,所以x的颜色要和node一致
        x.color = node.color;
        // 由于node要与父节点表示3节点,着红色
        node.color =  Node.RED;
        return flipColors(x);
    }

  (6)"红红黑"的第二种情况,新添加的红节点是之前红节点的右节点时,应该进行如下处理。

红红黑

  以上就为红黑树添加节点的所有可能的情况,对于这六种情况可以通过以下过程来进行自平衡的操作。实际上对于当前正在构建的节点只可能包含三种情况:红节点在当前节点的右孩子、当前节点的左孩子以及左孩子的左孩子为红节点、当前节点的左右孩子为红节点,对于第六种情况实际上在子节点的构建中已经变成了第五种情况。

总体流程

  对于其他两种情况,我们无需做任何操作,只需要在构建红黑树完成之后,手动的将红黑树的根节点着为黑色即可。
  

         private Node addNode(Node root, E e){
        // 使用e 构建子树,返回重构之后的树
        if(root == null) {
            size ++;
            return new Node(e);
        }
        // 根据 e 的值和当前值作比较,决定将 e 插入到左(右)子树中
        if(root.e.compareTo(e) < 0){
            root.right = addNode(root.right, e);
        }else if(root.e.compareTo(e) > 0){
            root.left = addNode(root.left, e);
        }

        //进行左旋
        if(isRed(root.right) && !isRed(root.left)){
            root = leftRotate(root);
        }
        //进行右旋
        if(isRed(root.left) && isRed(root.left.left)){
            root = rightRotate(root);
        }
        //颜色翻转
        if(isRed(root.left) && isRed(root.right)){
            root = flipColors(root);
        }
        // 构建完成之后,将重构之后的树返回
        return root;
    }

三. 扩展
  红黑树的删除节点、右倾红黑树(本文是左倾红黑树,也就是红节点在黑节点的左侧)、伸展树、算法导论中另一种红黑树的实现。

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