1.1 随处可见的红黑树

  • 1、知识树
  • 2、红黑树的性质(3)
  • 3、红黑树的使用(2)
  • 4、红黑树用在哪里(举例)
  • 5、判断是否为叶子节点的方法(2)
  • 6、红黑树的旋转
    • (1)左旋
    • (2)右旋
  • 7、操作红黑树结点(增删)的分情况讨论、原理和代码实现
    • (1)添加一个红黑树结点
    • (2)删除一个红黑树结点
  • 8、代码实现
  • 9、感谢大家的观看,我是COSMIC

本博客总结自零声教育的课程

本博客将和大家一起学习红黑树的相关知识,包括红黑树的性质、红黑树的左旋和右旋、红黑树增加、删除结点的原理,并在附有代码实现和讨论

1、知识树

2、红黑树的性质(3)

① 每个节点是红的或者黑的,根节点、叶子结点是黑色的
② 如果结点是红的,则两个儿子都是黑的(意思是红黑树中不能出现两个红色的结点相邻)
③ 对每个结点,从该节点到其子孙结点的所有路径上包含相同数目的黑结点(该条性质用来控制红黑树的平衡性,不是平衡所有结点,只是平衡的黑色结点的高度,平衡黑高)

(默认叶子结点都是黑色的)

(默认叶子结点都是黑色的,上图中没有画出叶子结点)

3、红黑树的使用(2)

★红黑树使用分两种情况:
①key,value:通过key查找对应的value
②利用红黑树的中序遍历,红黑树的中序遍历是顺序的

4、红黑树用在哪里(举例)

(1)map是红黑树的封装
(2)ngix
(3)定时器
(4)进程调度的cfs:用红黑树存储进程的集合,把调度的时间作为key值,每次从时间最小的值开始调度,即从红黑树的左下角开始查找
(5)内存管理:红黑树的平衡性使得我们能够更好地进行查找;表述一块内存有两种方法:①起始位置 + 长度 ②起始位置 + 结束位置,内存管理用红黑树进行存储的话,key的表示就是这两种方式

5、判断是否为叶子节点的方法(2)

① 判断左右子树是否同时为空
定义【一个公共的叶子结点】,看结点是否为这个公共的叶子结点,就能判断是否到达了叶子结点

6、红黑树的旋转

红黑树的旋转分为左旋和右旋:

左旋、右旋是我们实现红黑树的过程中的一个基础的原语操作,不要关注颜色

(1)左旋

左旋(逆时针旋转):x原本是y的父节点,现在将y变为x的父节点
★三步,每步对应修改一个树枝的两个方向,修改6个指针(因为每一个树枝对应两个方向的指针):
①将x的右子树指向y的左子树;若y的左子树不为叶子结点,则将y的左子树的父节点改为x的右子树

②将y的parent指向x的parent(判断x是否为根节点,即x的parent是否为叶子结点);原本x的parent的左子树或右子树指针指向y(先要判断x为x的parent的左子树还是右子树)

③将x的parent的指针指向y;将y的左子树的指针指向x

(2)右旋

右旋:复制上述代码,①将左右互换,②将x和y互换 就实现了,逻辑不需要修改
1、将y的左子树指向x的右子树,若x的右子树不为空则将x的右子树指向y

2、将x的parent指向y的parent,将y的parent指向x

3、将x的右子树指向y,y的parent指向x

7、操作红黑树结点(增删)的分情况讨论、原理和代码实现

(1)添加一个红黑树结点

如何插入一个结点:★新增加的一个结点,一定是加到非底层的叶子结点处
举例:若加一个结点,key为500,则加到图中红笔处:

在红黑树中插入一个结点,分为以下几种情况:

★★★在分情况讨论的时候一定要牢记两个点:
① 插入当前结点之前就是一棵红黑树
② 只讨论所插入的结点z是红色的

解读上图:
1、插入z结点,若z为黑色,则比较麻烦,建议直接看代码
2、插入z结点,若z为红色,则要z要插入的位置的父节点的颜色
(1)若父结点是黑色,则不需要调整,直接插入即可
(2)父节点是红色,祖父结点只能是黑色,此时要再按照叔父结点的颜色分为两类(知道叔父结点的颜色是为了方便做旋转):
① 若叔父结点是红色,则只有一种情况
② 若叔父结点是黑色,则还需要讨论两种情况:
a. 插入结点是父节点的左子树
b. 插入结点是父节点的右子树
注意:【若叔父结点是黑色的且下面还有叶子结点】这种情况不成立,因为父节点是红色的,所以若叔父结点是黑色的则只能是叶子结点

a. 若插入结点是父节点的右子树:先左旋,再修改颜色,再右旋
举例:

1)左旋344,将350放到344的位置上

2)右旋359,变成350、344、359(中左右)

b. 若插入结点是父节点的左子树:先修改颜色,再右旋
举例:
b. 叔父结点是红色的,此时不用看插入结点是父节点的左子树还是右子树,都是一样的:将父节点和叔父结点都变黑,将祖父结点变红即可,这样变换后插入结点的父节点就为黑色了,这时将红色的插入结点直接插入即可;变换颜色后,祖父结点388变成了红色,为了不让祖父结点和祖父的父节点颜色冲突,要将插入z结点变成祖父结点(将祖父结点赋值给z结点并递归调用),递归调用函数向上判断:

★红黑树左右子树高度差最多不超过2倍(2n-1)
举例:
若左子树高度是5,则右子树高度最多不超过9

(2)删除一个红黑树结点

有3个结点参与删除:
① 删除的key所对应的结点z
② 要删除的结点的后继结点y(注意要删除的结点不是key对应的结点,而是key对应的结点的后继节点)
③ 轴心结点x(后面需要调整的结点)
★★★过程:将y的值复制到z结点上,删除y结点,再调整x结点;z是要被覆盖的结点,y才是真正要被删除的结点

注意,若删除的y结点是黑色的,才需要调整;若y为红色则不需要调整

举例:这种情况下,删除key为172的结点(注意删除的不是key为172的结点,而是该节点的后继节点)

①删除的key所对应的结点z:key为172对应的结点
②所要删除的结点y(注意要删除的结点不是key对应的结点,而是key对应的结点的后继节点):key为206所对应的结点
③轴心结点x(后面需要调整的结点):key对224所对应的结点
★★★过程:将y(206对应的结点)的值复制到z结点上,删除y结点,再调整x结点

红黑树结点的删除的分情况讨论比较麻烦,建议直接看删除红黑树结点的代码;面试手撕红黑树结点的可能性不大,手撕红黑树代码主要能够帮助我们在以后的工作中修改底层源码。

8、代码实现

上述详细介绍了红黑树的相关原理,红黑树相关的代码均在我的github中,代码中每条语句都有详细的注释,以下是我的github代码链接,恳请大家批评指正!
GitHub代码
我自己实现的rbtree.c代码在rbtree文件夹中
课程中的参考代码在0voice文件夹的rbtree文件夹中

9、感谢大家的观看,我是COSMIC

COSMIC的后端学习之路——1.1 随处可见的红黑树相关推荐

  1. COSMIC的后端学习之路——1.3 海量数据去重的Hash与BloomFilter(布隆过滤器),bitmap(位图)

    1.3 海量数据去重的Hash与BloomFilter,bitmap 知识树 1.海量数据查找的应用场景 2.平衡二叉树 3.哪些算法涉及二分查找 4.散列表 (1)hash冲突 (2)负载因子 (3 ...

  2. COSMIC的后端学习之路——2.1 C++11新特性(1)

    2.1 C++11新特性(1) 知识树 1.智能指针 (1)std::shared_ptr:共享的智能指针 ①初始化 ②获取原始指针 ③指定删除器(自定义删除对象) ④一些错误用法 (2)std::u ...

  3. Java Web和Java后端学习之路

    摘要: 每个阶段要学习的内容甚至是一些书籍.针对Java Web和Java后端开发 java学习这一部分其实也算是今天的重点,这一部分用来回答很多群里的朋友所问过的问题,那就是我你是如何学习Java的 ...

  4. 学习数据结构(二叉树,平衡二叉树,红黑树,B树,B+树等),排序算法(冒泡排序 插入排序 快速排序 插入排序等)必须要知道的网页。

    以动图的形式让你更明白,数据的插入,查询路径.排序方法的比较过程. 更多的请点击Data Structure Visualizations

  5. 学习->C++篇十五:红黑树和map,set

    目录 一 . 红黑树的定义(规则): 二 . 红黑树是如何保持平衡的? 插入操作: 情况一:叔叔节点存在且为红色 情况二:叔叔节点不存在或存在且为黑色 三.map和set如何封装? 一 . 红黑树的定 ...

  6. 算法导论之红黑树的学习

    最近学习了二叉搜索树中的红黑树,感觉收获颇丰,在此写一篇文章小结一下学到的知识,顺便手写一下Java代码. 1.引言 先来讲讲什么是二叉搜索树,二叉搜索树有如下特点:他是以一颗二叉树(最多有两个子结点 ...

  7. 【实验室培训】大学生的Java后端开发学习之路(从App开发讲起)

    文章目录 前言 一.浅谈如何开发一款App 1.一个好的idea 2.根据这个idea完善好具体的需求 3.分工合作 4.设计阶段 ①UI设计 ②接口设计 ③架构设计 5.开发阶段 6.测试阶段 7. ...

  8. 我的mongo学习之路

    mongo学习之路 mongodb的安装,在这里就不做介绍了,不管是windows还是mac,网上都有教程,可以自行学习一下~~~ 一.启动 mongod 复制代码 二.链接 mongo 复制代码 三 ...

  9. pyqt5从子目录加载qrc文件_【JVM系统学习之路】一篇看懂类加载

    JVM系统学习之路系列演示代码地址:https://github.com/mtcarpenter/JavaTutorial 嗨喽,小伙伴大家好,我是小春哥,今天是打卡 [JVM系统学习之路] 的第二篇 ...

最新文章

  1. android手机播放pc音乐播放器,最强手机音乐播放器?Foobar2K安卓版体验
  2. 关于SQL语言的初步认识
  3. JavaScript 函数声明,函数表达式,匿名函数,立即执行函数之区别
  4. 《剑指offer》c++版本 10. 斐波那契数列
  5. UE4材质:纯数学算法实现水面水波扩散效果
  6. 关于未捕获异常的处理(WPF)
  7. java时间方法_JAVA处理日期时间常用方法
  8. 2021-2025年中国超声检查台行业市场供需与战略研究报告
  9. python for 格式化字符串 list.count
  10. docker本地构建kerberos单机环境
  11. 基于内容和用户画像的个性化推荐
  12. 2017网易校招:Fibonacci数列
  13. 群体遗传进化专题之选择性清除分析
  14. Prometheus监控报警系统入门
  15. Holy Grail 圣杯布局详解
  16. 中国移动为何要对手机上网流量封顶
  17. Maven 常用镜像站地址
  18. 如何用qt实现学生信息管理系统
  19. java毕业生设计宠物领养管理系统计算机源码+系统+mysql+调试部署+lw
  20. hypermill后处理构造器安装_NX后处理直白易操作教程

热门文章

  1. Pytorch:手把手教你搭建简单的卷积神经网络(CNN),实现MNIST数据集分类任务
  2. redis set 超时_Redis 更新(set) key值 会重置过期时间问题
  3. Linux Command snap 包管理
  4. 工控软件——驱动框架
  5. 领带的打法 (附图)
  6. 百度舆情平台助力政府企业高效应对舆情
  7. 美发管理系统:初学者入门级C++
  8. 如何把密度函数化为标准正态二维分布_概率ch3_2 边缘分布
  9. 读 近代汉地高僧 行谊
  10. Allegro 封装规范命名的重要性,切身体会!!