二叉树与红黑树

BST

二叉查找树就是一颗二叉树,他的左节点比父节点要小,右节点比父节点要大。他的高度决定的查找效率。

理想状态下,二叉树的增删改查的时间复杂度为O(LogN),最坏的情况为O(N)。当他的高度为LogN+1时,我们说二叉查找树是平衡的。下面盗图几张。
T key = a search key;   //查找的值
Node root = point to the root of a bst; //二叉树的根节点
while(true){
    if(root==null){
        return null;
    }
    if(root.value==key){
        return root;
    }else if(key.compareTo(root.value)<0){
        root = root.left;
    }else{
        root = root.righr;
    }
}
return null;

当查找BST时,先进行当前节点比较:

  • 如果相等的话就返回当前节点;
  • 如果比当前节点小,则继续查找当前节点的左节点;
  • 否则就继续查找当前节点的右节点。

直到当前节点指针为空或找到节点,查找结束。

BST的插入操作

Node node = create a new node;
Node root = point to the root of a bst; //二叉树的根节点
Node parent = null;

while(true){
    if(root==null) break;
    parent = root;
    if(node.value.compareTo(root.value)<0){
        root = parent.left;
    }else{
        root = parent.right;
    }
}
if(parent!=null){
    if(node.value.compareTo(root.value)<0){
        parent.left = node;
    }else{
        parent.right = node;
    }
}

插入BST时,先查找要插入的父节点。找到父节点后,通过比较与父节点的大小,决定要插入节点的位置。

BST的删除操作

  1. 查找到要删除的节点。

  2. 如果待删除的节点是叶子节点,则直接删除。

  3. 如果待删除的节点不是叶子节点,则先找到待删除节点的中序遍历的后继节点,用该后继节点的值替换待删除的节点的值,然后删除后继节点。

    中序遍历:先遍历左节点,然后遍历根节点,最后遍历右节点(根节点放中间)

BST存在的问题

BST存在的问题是,数在插入的时候会导致倾斜,不同的插入顺序会导致数的高度不一样,而树的高度直接影响了树的查找效率。理想的高度是LogN,最坏的情况所有的节点都在一条斜线上,这样树的高度为N。

红黑树Red-Black Tree(RBTree)

基于BST存在的问题,平衡查找二叉树(Balanced BST)产生了。平衡树的插入和删除的时候,会通过旋转操作将高度保持在LogN。其中两款具有代表性的平衡术分别为AVL树和红黑树。AVL树由于实现比较复杂,而且插入和删除性能差,在实际环境下的应用不如红黑树。

红黑树的实际应用非常广泛,如Java中的HashMap和TreeSet,Java 8中HashMap的实现因为用RBTree代替链表(链表长度>8时),性能有所提升。

RBTree的规则定义

1.任何一个节点都有颜色,红色或黑色
2.根节点是黑色的
3.父子节点之间不能出现两个连续的红节点
4.任何一个根节点,遍历到他的子孙节点,所经过的黑色节点数必须相同
5.空节点被认为是黑色的

  class Node<T>{
    public T value;
    public Node<T> parent;
    public boolean isRed;
    public Node<T> left;
    public Node<T> right;
}

因为以上规则的限制,保证了红黑树的自平衡。红黑树从根到叶子节点的最长路径不会超过最短路径的2倍。

RBTree的自平衡策略

当插入或删除节点时,红黑树的规则可能被打破,这时候就需要做出一些调整,来维持RBT的规则定义。调整包括变色,左旋转和右旋转。

变色

为了符合红黑树规则,尝试将节点颜色红色节点变为黑色,或将黑色节点变为红色。

旋转

旋转操作(Rotate)的目的是使节点颜色符合定义,让RBTree的高度达到平衡。
左旋转:被旋转的节点从左侧上升到父节点
右旋转:被旋转的节点从右侧上升到父节点

什么时候用变色,什么时候用旋转呢?

查了一些资料,插入和删除包含了很多情况,比较复杂。这里有个传送们:
30张图带你彻底理解红黑树

RBTree的插入操作

RBTree与BST的插入方式是一样的,只不过在插入之后,可能会导致树的不平衡,这时需要对树进行旋转操作和颜色修复(这里简称插入修复),使得他符合RBTree的定义。

新插入的节点颜色是红色,插入修复操作如果遇到父节点为黑色则修复操作结束。也就是说,只有在父节点为红色时是需要修复操作的。

当父节点为红色时,插入修复操作分以下三种情况:

  1. 叔叔节点也为红色。
  2. 叔叔节点为空,且祖父节点、父节点和新节点处于同一条斜线上。
  3. 叔叔节点为空,且祖父节点,父节点和新节点不处于同一条斜线上。

插入 - case1

如果叔叔节点也为红色,则将父节点,叔叔节点,祖父节点颜色互换,这样就符合了RBTree的定义。既维持了高度的平衡。下图中插入N节点,经过修复A、B、C节点颜色互换,如果A节点的父节点也为红色,则继续进行修复操作。


1566953856393.png

插入 - case 2

将B节点右旋,并且和父节点A互换颜色。如果B、C节点都是右节点,则将B节点左旋,然后与父节点A互换颜色就可以了。通过该修复操作的RBTree,高度和颜色都符合红黑树的定义。
1566966499559.png

插入 - case 3

1566967585800.png

现将C节点左旋,旋转后就将修复操作转换为 case 2。

插入操作总结

插入操作是一个向根节点回溯的操作,一旦牵涉的所有节点都符合红黑树的规则,则修复操作结束。之所以回回溯,是因为在进行case 1时,会将父节点颜色改变,有可能导致祖父节点不平衡,这时候就需要从祖父节点为起点,根据以上三种case做出调整。调整会一直到节点符合红黑树规则维泽,否则会一直到root节点结束,root节点永远是黑色的。

RBTree的删除操作

删除操作首先要做的是BST的删除操作,如果被删除的节点是叶子节点,则直接删除,如果是非叶子节点,会将该节点的中序遍历后继节点顶替要删除的节点。删除后就需要做删除修复操作,使RBTree符合定义,高度平衡。

删除修复操作在遇到删除节点是红色或到达root节点时结束修复。

删除操作是针对删除节点是黑色才有的(4. 任何一个根节点,遍历到他的子孙节点,经过的黑色节点必须相同),需要做的操作是从他的兄弟节点上借调黑色节点过来,如果没有黑色节点可以调用,则向上追溯,将每一级的黑色节点减1(??),使红黑树符合定义。

删除操作的总体思想是从兄弟节点借调黑色节点使树保持局部平衡,如果局部平衡达成了,就看整体树是否平衡,如果不平衡就向上追溯调整。

删除修复节点分为有多种情况,下面举两种例子:

  1. 待删除的节点的兄弟节点是红色的
  2. 待删除的节点的兄弟节点是黑色的,且兄弟节点所有子节点都是黑色的

...

删除 - case 1

由于兄弟节点是红色的,无法从兄弟节点借调,所以将兄弟节点通过左旋提升到父节点。这样case 1就可以转换成 case 2 ,case 3,case 4进行处理了。


1567039739689.png

删除 - case 2

由于兄弟节点及其所有的子节点都是黑色,所以可以将兄弟节点变红,这样就可以保证树的局部颜色定义了。继续向上调整,知道整棵树的颜色符合RBTree的定义为止。
1567040701594.png

删除总结

红黑树的删除是最复杂的操作,复杂在于删除黑色节点的时候,如何从兄弟节点调用,以保证树符合定义。

总结

作为二叉查找树中面众多的实现之一,红黑树通过引入颜色的概念,通过颜色约束的使用,包括变色和旋转,来保持树的高度平衡。即使在最坏的情况下,操作的时间复杂度也为O(LogN),原因是整个红黑树的高度保持是LogN(因为旋转修复)。

参考文章:

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

推荐阅读更多精彩内容

  • 红黑树是平衡二叉查找树的一种。为了深入理解红黑树,我们需要从二叉查找树开始讲起。 BST 二叉查找树(Binary...
    kanehe阅读 1,370评论 0 8
  • 引自:https://zhuanlan.zhihu.com/p/24367771Java代码实现 红黑树是平衡二叉...
    Magic11阅读 219评论 0 0
  • 注:本文对网上一些博客进行详细与修正,并给出C语言实现 红黑树是平衡二叉查找树的一种。为了深入理解红黑树,我们需要...
    molscar阅读 413评论 0 2
  • 红黑树是一种近似平衡的二叉查找树,它能够确保任何一个节点的左右子树的高度差不会超过二者中较低那个的一陪。具体来说,...
    navyd阅读 419评论 0 0
  • 前几天看了朋友圈转发的文章,一篇跟深圳有关的文章,讲得是我们这代人对大城市的向往与无奈。虽然文章中透露着很多激励的...
    杂货店的故事阅读 217评论 0 1