介绍红黑树之前,我们先来简单了解下二叉查找树(BST)。

首先我们看下二叉查找树的特性:

1.若任意节点的左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值。

2.若任意节点的右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值。

3.左、右子树也分别为二叉排序树。

如上图,这是一颗二叉树,如果我们要查询7,那么只要先跟8比,然后再跟3比,再跟6比,然后找到7,我们可以发现,这正是二分查找的思想,查询二叉树中的一个数据,最大的查询次数就是这颗树的高度。同理,当插入数据的时候,也是从根节点开始依次比较找到位置,再插入。但是二叉树也存在着缺陷,那就是当出现跛脚树的时候,二叉树就会变成了线性查找。举个例子。我们有一个根节点8,如果依次插入7,6,5,4,那么这棵二叉树就会变成下面这个模样:

我去,这还是我认识的树嘛。。。我们发现,树的高度就是元素的个数,查询效率变成了O(n)。为了解决二叉树的平衡问题,下面我们就来引出主角--红黑树(Red–black tree)。

红黑树(英语:Red–black tree)是一种自平衡二叉查找树,是每个节点都带有颜色属性的二叉查找树,颜色为红色或黑色。在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求:

  1. 节点是红色或黑色。
  2. 根是黑色。
  3. 所有叶子都是黑色(叶子是NIL节点)。
  4. 每个红色节点必须有两个黑色的子节点。(从每个叶子到根的所有路径上不能有两个连续的红色节点。)
  5. 从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点。

下图是一颗红黑树

这5个特性,确保了二叉树的大致平衡:从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。(最长路径为黑和红相间隔,最短路径为全黑节点)

当有插入和删除操作的时候,红黑树的平衡最容易被打破,接下来我们详细分析下各种场景下的破坏,红黑树是如何保持平衡的。

插入

这里先明确一个点,我们把新插入的节点标记为红色(为什么呢?如果设为黑色,就会导致根到叶子的路径上有一条路上,多一个额外的黑节点,这个是很难调整的。但是设为红色节点后,可能会导致出现两个连续红色节点的冲突,那么可以通过1⃣️变色和2⃣️树旋转来调整。)

为了便于理解,现在开头和大家普及几个概念。(祖父节点,叔节点)

class Node {  Object value;int color;Node left, right, parent;
}
//祖父节点
Node grandparent(Node n) {return n.parent.parent;
}
//叔叔节点
Node uncle(Node n) {if(n.parent == grandparent(n).left)return grandparent(n).right;elsegrandparent(n).left;
}复制代码

插入场景1(变色):这个场景比较简单,首次插入,根节点

void insert_case1(Node n){if(n.parent == NULL)    //根节点直接把颜色变黑就行了(变色)n.color = BLACK;return;else    //否则,进入场景2insert_case2 (n);
}复制代码

插入场景2:父节点为黑色,直接插入红色节点就行了(新插入的节点是在原先的叶子节点,不会有两个红色相连的问题)

void insert_case2(Node n){if(n.parent.color == BLACK)return; //父节点为黑色,直接插入红色节点就行了(不用操作)else    //否则insert_case3 (n);
}复制代码

插入场景3(变色):此时父节点存在且为红色,那么祖父的节点肯定是黑色。那么要看uncle节点的情况。假设uncle节点的颜色是红色的

void insert_case3(Node n){//如果uncle节点的颜色是红色的if(uncle(n) != NULL && uncle(n).color == RED) {n.parent.color = BLACK; //把父节点变黑uncle(n).color = BLACK; //uncle节点变黑grandparent(n).color = RED; //祖父节点变红//此时祖父节点以下的都已经平衡了,剩下的就是要把祖父节点当作新插入的节点,去递归调用一下场景1开始的流程insert_case1(grandparent(n));}  else//如果uncle节点是黑色的,那么看下场景4insert_case4 (n);
}复制代码

场景3操作图如下:

插入场景4(左旋或者右旋):此时父节点为红色,祖父节点是黑色,uncle节点只能为NIL节点(因为uncle为黑的话,就违反了特性5)

void insert_case4(Node n){//如果n为右节点,n的父节点p为祖父节点g的左节点,如下图if(n == n.parent.right && n.parent == grandparent(n).left) {rotate_left(n.parent); //n的父节点执行--左旋操作//旋转完成后,n指向自己的左节点(这样就变成了场景5的一种情形:自己是左节点,且父节点是祖父节点的左节点)n = n.left;} else if(n == n.parent.left && n.parent == grandparent(n).right) {//如果自己是左节点,且父节点为右节点rotate_right(n.parent); //n的父节点执行--右旋操作//旋转完成后,n指向自己的右节点(这样就变成了场景5的另一种情形:自己是右节点,且父节点是祖父节点的右节点)n = n.right;}//场景4的操作结果,或者直接满足场景5的,都将进入场景5做最后的操作insert_case5 (n);
}复制代码

场景4操作图如下:

插入场景5:执行变色,以及祖父节点的旋转

void insert_case5(Node n){//首先执行变色操作,把n的父节点变黑,n的祖父节点变红n.parent.color = BLACK;grandparent(n).color = RED;//如果n为左节点,n的父节点p为n祖父节点G的左节点(如图5-1)if(n == n.parent.left && n.parent == grandparent(n).left) {//n的祖父节点G右旋转rotate_right(grandparent(n));} else {//n为右节点,n的父节点p为n的祖父节点G的右节点(如图5-2)//n的祖父节点G左旋转rotate_left(grandparent(n));}}复制代码

如5-1和5-2步骤图所示,执行完毕后,从这棵子树的根节点P到叶子节点的所有黑色节点数是2,与N插入前一样(满足特性5),又因为P为黑色,不会违反红黑树的其他特性(特性1~4),所以,我们插入的步骤就全部完成了。

删除

如果需要删除的节点有两个儿子,那么问题可以被转化成删除另一个只有一个儿子的节点的问题,对于二叉查找树,在删除带有两个非叶子儿子的节点的时候,我们要么找到它左子树中的最大元素、要么找到它右子树中的最小元素,并把它的值转移到要删除的节点中。剩下的就是变色和旋转的操作了,篇幅有限,这里就不往下说了。

转载于:https://juejin.im/post/5bef5de46fb9a049c15ecbd9

红黑树--(高清无码图+代码)演示相关推荐

  1. 趣味算法图解,高清无码图免费下载

    作者 | Sándor P. Fekete 整理 | 程序员小吴 前言 今天分享一个适合初学者更好的学习算法的网站---- IDEA . https://idea-instructions.com/ ...

  2. 获取《王者荣耀》全英雄高清无码图

    前言 最近看到有网友爬<王者荣耀>全英雄皮肤图,觉得挺有意思的:也顺便记录下自己在分析爬虫的过程. 正文 0x01分析 首先打开http://pvp.qq.com/web201605/he ...

  3. Swift开发小技巧--扫描二维码,二维码的描边与锁定,设置扫描范围,二维码的生成(高清,无码,你懂得!)...

    二维码的扫描,二维码的锁定与描边,二维码的扫描范围,二维码的生成(高清,无码,你懂得!),识别相册中的二维码 扫描二维码用到的三个重要对象的关系,如图: 1.懒加载各种类 // MARK: - 懒加载 ...

  4. 分享20个无版权的高清无码图库站

    今天这组网站比较有特色,有专门分享美食图片的,有专门分享复古图片的,各领风骚,质量都是一顶一的棒.下面就是20个无版权的高清无码图库站,记得收藏啊. 您可能感兴趣的相关文章 35款精致的 CSS3 和 ...

  5. 神器 | 一键下载海量高清无码壁纸

    文 | 豆豆 来源:Python 技术「ID: pythonall」 电脑默认的壁纸简直不是太难看,今天给大家介绍一个拥有海量壁纸的网站,即使你一天换一张也取之不尽用之不竭,网址如下: https:/ ...

  6. 一起玩转算法面试,保姆级攻略(附高清无码算法总结导图),建议收藏

    本文已收录至启舰的电子书<逆天改命-程序员的成神之路>,github地址:https://github.com/harvic/FightingCoder  欢迎star.点击[阅读原文]也 ...

  7. 华为 A199 / Ascend G710摄像头拍摄样张 多图 高清无码 慎入

    前方高能反应,华为 A199 / Ascend G710摄像头拍摄样张,多图.高清.无码!   废话少说,直接来个连拍的,发现华为A199的连拍速度还不错,不过连拍的张数比较少 今天的天气灰蒙蒙的,但 ...

  8. 电子漫画系列套图更新11张,共计83张,附高清无码下载链接

    编辑:晓宇,排版:晓宇 微信公众号:芯片之家(ID:chiphome-dy) 电子漫画 电子漫画系列作品,从18年开始陆陆续续更新了多次,新关注的小伙伴可能还不知道在哪里获取,好多人在后台找我要,很多 ...

  9. 分享20个无版权的高清无 码图库站

    今天这组网站比较有特色,有专门分享美食图片的,有专门分享复古图片的,各领风骚,质量都是一顶一的棒.下面就是20个无版权的高清**图库站,记得收藏啊. Compfight Compfight 是一个图片 ...

最新文章

  1. AI芯片:从历史看未来
  2. pytorch cpu gpu性能对比
  3. mysql select操作
  4. web开发快速提高工作效率的一些资源
  5. PoW 本质上是个去中心化的时钟
  6. AS3中 is,as,typeof的区别 .
  7. Jzoj5429 排列
  8. Pytorch 配置 Tensorboard 可视化学习(一)
  9. (43)System Verilog 类中变量随机化
  10. python使用redis有序集合_Redis 有序集合(sorted set)
  11. 在手语世界里,健听人、数字人与听障人的交织
  12. nodejs如何实现ajax,nodejs + express怎么实现Ajax方式及其简单功能
  13. Java出现OutOfMemoryError
  14. mathorcup数据大赛
  15. 用了五年 VS Code ,我决定换成 JetBrains……
  16. 三行情书 计算机网络,“学霸式”三行情书走红!句子很短,爱你如诗
  17. Linux环境Java给图片加水印中文乱码处理
  18. stm32f4实现s6d1121+xtp2046触摸屏功能
  19. 简单漫画读懂联邦学习
  20. Linux的体系结构

热门文章

  1. 阿里云API网关调用示例
  2. arduino 感光灯
  3. 这下,大学生日子难过了!
  4. 【面试题】 10.11. 峰与谷
  5. 西普实验吧CTF-约瑟夫环
  6. C++实现二路归并排序算法
  7. 闭区间上的连续函数必定是一致连续的
  8. 拷贝PDF中文字出现英文乱码的问题
  9. oracle矩阵转置,法线变换、逆转置、伴随转置
  10. 什么是梯度?为什么梯度的方向总是指向函数值增大的方向?