我们在上一篇博客认识到了平衡二叉树(AVLTree),了解到AVL树的性质,其实平衡二叉树最大的作用就是查找,AVL树的查找、插入和删除在平均和最坏情况下都是O(logn)。AVL树的效率就是高在这个地方。如果在AVL树中插入或删除节点后,使得高度之差大于1。此时,AVL树的平衡状态就被破坏,它就不再是一棵二叉树;为了让它重新维持在一个平衡状态,就需要对其进行旋转处理, 那么创建一颗平衡二叉树的成本其实不小. 这个时候就有人开始思考,并且提出了红黑树的理论,那么红黑树到底比AVL树好在哪里?

红黑树与AVL树的比较:

1.AVL树的时间复杂度虽然优于红黑树,但是对于现在的计算机,cpu太快,可以忽略性能差异
2.红黑树的插入删除比AVL树更便于控制操作
3.红黑树整体性能略优于AVL树(红黑树旋转情况少于AVL树)

红黑树的性质:

红黑树是一棵二叉搜索树,它在每个节点增加了一个存储位记录节点的颜色,可以是RED,也可以是BLACK;通过任意一条从根到叶子简单路径上颜色的约束,红黑树保证最长路径不超过最短路径的二倍,因而近似平衡。

具体性质如下:

  1. 每个节点颜色不是黑色,就是红色
  2. 根节点是黑色的
  3. 如果一个节点是红色,那么它的两个子节点就是黑色的(没有连续的红节点)
  4. 对于每个节点,从该节点到其后代叶节点的简单路径上,均包含相同数目的黑色节点

那么为什么当满足以上性质时,就能保证最长路径不超过最短路径的二倍了呢?我们分析一下:

你的最短路径就是全黑节点,最长路径就是一个红节点一个黑节点,最后黑色节点相同时,最长路径刚好是最短路径的两倍

红黑树的插入:

红黑树插入节点过程大致分析:

  • RBTree为二叉搜索树,我们按照二叉搜索树的方法对其进行节点插入
  • RBTree有颜色约束性质,因此我们在插入新节点之后要进行颜色调整

具体步骤如下:

  1. 根节点为NULL,直接插入新节点并将其颜色置为黑色
  2. 根节点不为NULL,找到要插入新节点的位置
  3. 插入新节点
  4. 判断新插入节点对全树颜色的影响,更新调整颜色

首先红黑树的插入其实不是那么容易实现的,以前搜索树的插入我们很容易理解现在我们首先思考一个问题,你插入节点的默认颜色是RED或BLACK? 这里我们需要根据性质来思考,首先如果插入黑节点,这个可以直接插入无论它的父亲是什么颜色,但是红黑树的性质是每条路径的黑色节点数目相同这个时候你再想想那其他路径的黑色节点数目一定比你现在少一个节点,所以调整起来是非常繁琐的. 插入红节点不需要调整其他路径,如果它的父亲为黑,那么直接插入,如果他的父亲为红那么在该路径上面开始分情况调整. 所以插入节点默认颜色一定要为红.如果为黑调节成本太大了.
接下来开始插入节点如果插入节点的父亲为黑那么直接插入后返回不需要做任何调整. 但是如果插入节点的父亲为红,那么就需要调整了.具体的调整过程可以分为三个情况:

1.第一种情况
cur为红,parent为红,pParent为黑,uncle存在且为红
则将parent,uncle改为黑,pParent改为红,然后把pParent当成cur,继续向上调整。

此时对该子树进行操作,parent节点和uncle节点变为黑,pParent节点变为红,这样我们就保证该子树中每条路径中黑色节点相同并且没有连续的红节点,然后再让cur等于pParent节点继续往上继续调整。

2. 第二种情况
cur为红,parent为红,pParent为黑,uncle不存在/u为黑
parent为pParent的左孩子,cur为parent的左孩子,则进行右单旋转;

uncle不存在:

uncle存在且为黑:

相反,parent为pParent的右孩子,cur为parent的右孩子,则进行左单旋转;
p、g变色–p变黑,g变红.

uncle不存在:

uncle存在且为黑:

3.第三种情况
cur为红,p为红,g为黑,u不存在/u为黑
p为g的左孩子,cur为p的右孩子,则针对p做左单旋转
则转换成了情况2
uncle不存在:

uncle存在且为黑:

相反,p为g的右孩子,cur为p的左孩子,则针对p做右单旋转
则转换成了情况2
uncle不存在:

uncle存在且为黑:

红黑树插入节点代码实现如下:

bool Insert(const K& key, const V& value){//根节点为空if (_root == NULL){_root = new Node(key,value);_root->_color = BLACK;return true;}//根节点不为空//找到新节点插入位置Node* parent = NULL;Node* cur = _root;while (cur){if (cur->_key < key){parent = cur;cur = cur->_right;}else if (cur->_key >key){parent = cur;cur = cur->_left;}elsereturn false;}//插入新节点cur = new Node(key, value);cur->_color = RED;if (parent->_key > key){parent->_left = cur;cur->_parent = parent;}else//parent->_key < key{parent->_right = cur;cur->_parent = parent;}//插入节点后颜色的调整while (parent && parent->_color == RED){Node* grandfather = parent->_parent;//grandfather颜色一定为黑色if (parent == grandfather->_left){Node* uncle = grandfather->_right;//uncle存在且为红if (uncle && uncle->_color == RED){parent->_color = uncle->_color = BLACK;grandfather->_color = RED;cur = grandfather;parent = cur->_parent;}else//uncle不存在/uncle存在且为黑{if (cur == parent->_right){RotateL(parent);swap(parent, cur);}RotateR(grandfather);parent->_color = BLACK;grandfather->_color = RED;}}else//grandfather->_right==parent{Node* uncle = grandfather->_left;//uncle存在且为红if (uncle && uncle->_color == RED){parent->_color = uncle->_color = BLACK;grandfather->_color = RED;cur = grandfather;parent = cur->_parent;}else//不存在/存在且为黑{if (cur == parent->_left){RotateR(parent);swap(cur, parent);}RotateL(grandfather);parent->_color = BLACK;grandfather->_color = RED;}}}//end while (parent && parent->_color == RED)_root->_color = BLACK;return true;}

浅析红黑树(RBTree)原理及实现相关推荐

  1. 红黑树RBTree原理(超易懂)

    红黑树脑图 目录 文章目录 红黑树的定义 四点特征 为什么红黑树是近似平衡的 (1)首先,我们来看,如果我们将红色节点从红黑树中去掉,那单纯包含黑色节点的红黑树的高度是多少呢? (2)现在把红色节点加 ...

  2. 数据结构 — 浅析红黑树原理以及实现

    浅析红黑树原理以及实现 我们在上一篇博客认识到了平衡二叉树(AVLTree),了解到平衡二叉树的性质,其实平衡二叉树最大的作用就是查找,AVL树的查找.插入 和删除在平均 和 最坏情况下都是O(log ...

  3. 左倾红黑树的原理及简单实现

    (注:以下图片全部源于<算法 第4版>) 左倾红黑树的原理及简单实现 左倾红黑树的简介 左倾红黑树的定义 左倾红黑树与2-3树的对比 左倾红黑树的颜色表示 左倾红黑树的一些基本操作 1.颜 ...

  4. 红黑树结构原理的图文讲解(非代码)

    1.引言 HashMap的基本结构是数组,链表和红黑树.以数组为基本形态,数组中的元素先以链表形式储存,当链表的长度超过8时(包含数组上的那个链表头)就会将链表转换为红黑树,以加快修改和查询效率.当然 ...

  5. 红黑树(RB-Tree)比AVL强在哪?

    前言 以前本科同学在找工作的时候,就被面试官问到过关于红黑树的问题.因为当时我的知识面不广,所以也不知道红黑树是个什么东西,也没放在心上.在看过了STL源码后才知道原来有很多底层实现都用的红黑树.简单 ...

  6. 红黑树的原理以及实现

    红黑树 红黑树基于二叉查找树的附加特性 节点是红色或黑色. 根节点是黑色. 每个叶子节点都是黑色的空节点(叶子结点指为空的叶子结点). 每个红色节点的两个子节点都是黑色的(从每个叶子到根的所有路径上不 ...

  7. C++ 泛型编程 实现红黑树RBTree

    代码如下: #include <iostream> #include <ctime> using namespace std;enum COLOR {BLACK,RED };t ...

  8. 红黑树 之 原理和算法详细介绍

    概要 目录 1 红黑树的介绍 2 红黑树的应用 3 红黑树的时间复杂度和相关证明 4 红黑树的基本操作(一) 左旋和右旋 5 红黑树的基本操作(二) 添加 6 红黑树的基本操作(三) 删除 作者:Sk ...

  9. 红黑树算法原理(从二叉搜索树讲起)

    原文:红黑树深入剖析及Java实现,本文修改了原文的一些小错误,如果想看红黑树的Java实现可以到原文去看. 红黑树是平衡二叉查找树的一种.为了深入理解红黑树,我们需要从二叉查找树开始讲起. BST ...

最新文章

  1. recover 没有捕获异常_GO语言异常处理机制panic和recover分析
  2. C++异常 返回错误码
  3. 黄海广博士的github镜像下载(机器学习及深度学习资源)
  4. 中国到底有多少个.NET 程序员?都在哪个城市写代码?
  5. android 自定义actionbar,如何让android的actionbar浮动且透明
  6. 使用 nohup 设置后台进程
  7. 连 CEO 都不香了?这些互联网大佬接连辞任
  8. Hadoop Shell总结
  9. Java、LotusScript和JavaScript中的自定义事件编程
  10. word如何弄成两竖列_Word中怎么将文字改成竖排显示
  11. apipost中文版
  12. MT 101 Request for Transfer转账请求
  13. Scratch -> C++画图->信奥(C++)学习导航
  14. 全球与中国聚 (3,4-亚乙基二氧噻吩) (PEDOT)市场深度研究分析报告
  15. 什么是格局?如何提升自我格局?做到这一点就够了!
  16. 国产迪王耀全球(下)
  17. 【面试题】N阶台阶,每次走一步或两步,计算共有多少种走法,并将每种走法打印出来。
  18. 多并发编程基础 之协成
  19. 2022-10-20 Linux自带LED灯驱动gpio-leds 心跳呼吸灯heartbeat、定时器timer的使用
  20. jquery-editable-select使用 绑定动态数据

热门文章

  1. js添加多个子节点_JS原生追加子节点
  2. DBCO-PEG-NIR-II dyes |二苯并环辛炔-聚乙二醇-近红外二区染料|的储存条件
  3. 如何查看python安装位置图_如何查看pymysql 安装成功
  4. 机器学习——BP神经网络详细介绍及案例Python代码实现
  5. 收集整理Matlab中的linprog函数使用说明
  6. 2022-2028年中国山茱萸行业投资策略探讨及市场规模预测报告
  7. httpie请求使用
  8. 西安高端的软装设计公司
  9. Android 播放视频的方法+播放测试地址 http
  10. #37 删除字符串中连续的重复字符