前言

  11.1新的一月加油!这个购物狂欢的季节,一看,已囊中羞涩!赶紧来恶补一下红黑树和2-3树吧!红黑树真的算是大名鼎鼎了吧?即使你不了解它,但一定听过吧?下面跟随我来揭开神秘的面纱吧!

  一、2-3树

  1、抢了红黑树的光环?

  今天的主角是红黑树,是无疑的,主角光环在呢!那2-3树又是什么鬼呢?学习2-3树不仅对理解红黑树有帮助,对理解B类树,也是有巨大帮助的,所以学习2-3树很必要!

  2、基本性质

  2-3树满足二分搜索树的基本性质,但节点可以存放一个元素或两个元素!如下图,就是2-3树:

  

  说明:2-3树一颗绝对平衡的树(绝对平衡:对于任意一个节点,左右子树高度相同)

  3、维护绝对平衡

  2-3树在插入过程中如何维护绝对平衡呢?进行画图演示,实在有点不好画,如下图:

  

  说明:

  1、不能将新节点插入到空节点

    因为那样如上图,就不满足绝对平衡了,所以可以将37和42合并,2-3支持3节点。

  2、不支持4节点,进行拆分

    再插入12时,也不能插入空节点,也要合并,但2-3树不支持4节点,所以进行进行拆分。

  3、子节点达到3节点,合并到父节点

    再依次插入18、6,达到4节点,进行拆分,但不符合绝对平衡了怎么办?将12和37合并,就形成了最后3节点的图了

  总结:讲到这里,应该对2-3树如何维护绝对平衡,应该了解了吧?理解2-3树,对于再理解红黑树,是非常有帮助的,其实,它们有等价性的,接下来会说明的。

  二、红黑树

  1、红黑树和2-3树的等价性

  也想达到像2-3树那样的绝对平衡,但2-3树的实现比较麻烦,所以产生了红黑树;那么,红黑树和2-3树有怎么样的等价性呢?如下图:

  

  说明:红黑树最开始想用红线区别b、c,但实现起来比较困难,然后用红黑来表示节点,就比较好实现了!

  红黑树和2-3树总体对比图,可以参考一下:

  

  2、红黑树5个重要性质

  1、引自《算法导论》

  红黑树有五个重要性质,引自算法界一本圣洁《算法导论》中的内容,如下:

  

  是不是看着有点晕,下面我进行解释。

  2、5个重要性质

  1、每一个节点或者红色的,或是黑色的

  2、根节点是黑色的

  3、每一个叶子节点(最后的空节点)是黑色的

  4、如果一个节点是红色的,那么它的孩子节点都是黑色的

  5、从任意节点到叶子节点,经过的黑色节点是一样的

  

  解释:最重要的性质是第五条,前4条在理解2-3树之后,就很好理解了,第5条性质说明了:红黑树是保持“黑平衡”的二叉树;

严格意义上来说,红黑树不是平衡二叉树,最大高度:2logn,但是时间复杂度仍然是O(logn),因为2是常数,但比AVL树查询要稍微慢一些。

  三、红黑树添加元素

  红黑树添加元素,比较繁琐,因为要保持上面的五个性质,要不然就不是红黑树了;

  1、保持根节点为节点

  红黑树的节点类也可以从二分搜索树上进行修改,但要新增“color”成员变量,来标注节点颜色,节点类如下:

template<typename Key, typename Value>
class RBTree {
private:static const bool RED = true;static const bool BLACK = false;struct Node {Key key;Value value;Node *left;Node *right;bool color;Node(Key key, Value value) {this->key = key;this->value = value;this->left = this->right = nullptr;color = RED;  //默认初始化为红色}Node(Node *node) {this->key = node->key;this->value = node->value;this->left = node->left;this->right = node->right;this->color = node->color;}};Node *root;int size;
}

  因为红黑树性质1要求根节点为黑色,所以要保持根节点为黑色;

  2、左旋转

  像AVL树一样,红黑树也需要左旋和右旋,如下图就需要左旋转,因为“红色节点是左倾斜的”:

  

  说明:图中黑色字体标识黑色节点,红色表示红色节点,并演示了旋转过程,最后还要改变节点颜色。

  3、左旋转代码实现

  代码如下:

  

Node *leftRotate(Node *node) {Node *x = node->right;node->right = x->left;x->left = node;x->color = node->color;node->color = RED;return x;}

  4、颜色反转

  下面这种情况就需要颜色反转,如下图:

  

  

  5、颜色反转代码实现

  代码如下:

void flipColors(Node *node) {node->color = RED;node->left->color = BLACK;node->right->color = BLACK;}

  6、右旋转

  下面情况需要右旋转,如下图:

  

    旋转之后,如下图:

  

   7、右旋转代码如下

  代码如下:

  

Node *rightRotate(Node *node) {Node *x = node->left;node->left = x->right;x->right = node;x->color = node->color;node->color = RED;return x;}

  8、总体流程图

  

  9、总体代码

  总体代码如下,供参考和学习:

#ifndef RED_BLACK_TREE_RBTREE_H
#define RED_BLACK_TREE_RBTREE_H#include <iostream>
#include <vector>template<typename Key, typename Value>
class RBTree {
private:static const bool RED = true;static const bool BLACK = false;struct Node {Key key;Value value;Node *left;Node *right;bool color;Node(Key key, Value value) {this->key = key;this->value = value;this->left = this->right = nullptr;color = RED;}Node(Node *node) {this->key = node->key;this->value = node->value;this->left = node->left;this->right = node->right;this->color = node->color;}};Node *root;int size;public:RBTree() {root = nullptr;size = 0;}~RBTree() {destroy(root);}int getSize() {return size;}int isEmpty() {return size == 0;}bool isRed(Node *node) {if (node == nullptr) {return BLACK;}return node->color;}void add(Key key, Value value) {root = add(root, key, value);root->color = BLACK;}bool contains(Key key) {return getNode(root, key) != nullptr;}Value *get(Key key) {Node *node = getNode(root, key);return node == nullptr ? nullptr : &(node->value);}void set(Key key, Value newValue) {Node *node = getNode(root, key);if (node != nullptr) {node->value = newValue;}}private:// 向以node为根的二叉搜索树中,插入节点(key, value)// 返回插入新节点后的二叉搜索树的根Node *add(Node *node, Key key, Value value) {if (node == nullptr) {size++;return new Node(key, value);}if (key == node->key) {node->value = value;} else if (key < node->key) {node->left = add(node->left, key, value);} else {node->right = add(node->right, key, value);}if (isRed(node->right) && !isRed(node->left)) {node = leftRotate(node);}if (isRed(node->left) && isRed(node->left->left)) {node = rightRotate(node);}if (isRed(node->left) && isRed(node->right)) {flipColors(node);}return node;}// 在以node为根的二叉搜索树中查找key所对应的NodeNode *getNode(Node *node, Key key) {if (node == nullptr) {return nullptr;}if (key == node->key) {return node;} else if (key < node->key) {return getNode(node->left, key);} else {return getNode(node->right, key);}}void destroy(Node *node) {if (node != nullptr) {destroy(node->left);destroy(node->right);delete node;size--;}}Node *leftRotate(Node *node) {Node *x = node->right;node->right = x->left;x->left = node;x->color = node->color;node->color = RED;return x;}Node *rightRotate(Node *node) {Node *x = node->left;node->left = x->right;x->right = node;x->color = node->color;node->color = RED;return x;}void flipColors(Node *node) {node->color = RED;node->left->color = BLACK;node->right->color = BLACK;}
};#endif //RED_BLACK_TREE_RBTREE_H

View Code

  总结  

  面试时99.9%不会让手写一下红黑树的添加过程,除非你面试算法工程师,那就打扰了!主要理解红黑树的性质、左旋和右旋等。

  欢迎点赞和评论,感谢支持!

转载于:https://www.cnblogs.com/liudw-0215/p/9887951.html

大名鼎鼎的红黑树,你get了么?2-3树 绝对平衡 右旋转 左旋转 颜色反转相关推荐

  1. mysql索引 红黑树_为什么MySql索引使用B+树?

    前言 面试中我们经常碰到面试官问到数据库索引,问到索引就会问你索引的数据结构.类似这种数据结构对于普通程序员来说记住概念几天就忘了,而且概念不是每个人都能很好都理解,所以针对这一原因,我简单通俗都像大 ...

  2. 自顶向下红黑树java,【CPP】各种各样的树(9)——自顶向下的红黑树

    当前浏览器不支持播放音乐或语音,请在微信或其他浏览器中播放 本以为春节后马上就能写完这些树了,结果没想到一拖再拖居然拖到了开学前,很真实.红黑树还是蛮难的,写着写着才意识到应该先搞完B树然后再写2-3 ...

  3. MySQL数据库的红黑树优化_为什么Mysql用B+树做索引而不用B-树或红黑树

    B+树做索引而不用B-树 那么Mysql如何衡量查询效率呢?– 磁盘IO次数. 一般来说索引非常大,尤其是关系性数据库这种数据量大的索引能达到亿级别,所以为了减少内存的占用,索引也会被存储在磁盘上. ...

  4. TreeMap实现原理 红黑树

    TreeMap的实现是红黑树算法的实现,所以要了解TreeMap就必须对红黑树有一定的了解,其实这篇博文的名字叫做:根据红黑树的算法来分析TreeMap的实现,但是为了与Java提高篇系列博文保持一致 ...

  5. 用最简单的话讲最明白的红黑树

    前言 首先初生牛犊不怕虎,我想反驳一下许多许多大佬对红黑树中颜色属性的看法.如有冒犯,请忍回去. 大佬的看法: 红黑树是对2-3-4阶树(多路平衡查找树)概念的实现.红色节点是为了和黑色父节点结合形成 ...

  6. HashMap(2)之红黑树

    我们知道,JDK1.8 之后,HashMap 的底层数据结构类型为数组+链表+红黑树.红黑树本质上是一种二叉查找树,为了保持平衡,它又在二叉查找树的基础上增加了一些规则: 1.每个树节点要么是红色,要 ...

  7. 为什么有红黑树?什么是红黑树?看完这篇你就明白了

    为什么要有红黑树 想必大家对二叉树搜索树都不陌生,首先看一下二叉搜索树的定义: 二叉搜索树(Binary Search Tree),或者是一棵空树,或者是具有下列性质的二叉树:若它的左子树不空,则左子 ...

  8. 为什么要有红黑树?什么是红黑树?画了20张图,看完这篇你就明白了

    为什么要有红黑树 想必大家对二叉树搜索树都不陌生,首先看一下二叉搜索树的定义: 二叉搜索树(Binary Search Tree),或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左 ...

  9. AVL树、splay树(伸展树)和红黑树比较

    AVL树.splay树(伸展树)和红黑树比较 一.AVL树: 优点:查找.插入和删除,最坏复杂度均为O(logN).实现操作简单 如过是随机插入或者删除,其理论上可以得到O(logN)的复杂度,但是实 ...

最新文章

  1. 2018-2019-1 20165318《信息安全系统设计基础》第八周课上测试
  2. H5嵌入原生开发小结----兼容安卓与ios的填坑之路
  3. python应用:最长无重复字串提取
  4. JS中document和window的区别
  5. Ajax初体验(一)
  6. MIT Kimera阅读笔记
  7. python 后缀 .py .pyc .pyw .pyo .pyd的区别
  8. Windows服务开发相关文章收集
  9. 多线程测试时的辅助类--CountDownLatch
  10. 易语言超级列表框怎么设置文本颜色_抖音超火的快闪动画怎么做?手把手教你!三分钟学会...
  11. 武汉大学计算机科学与技术培养方案,武汉大学计算机学院培养方案(2018版)
  12. php对接建行h5网页支付
  13. python爬虫获取试题(仅提供逻辑和部分代码,不提供完整实例)
  14. @Profile 注解的介绍
  15. CMMI3-CMMI5评估认证需要遵循七大原则
  16. 在OpenCV里使用背景去除
  17. Excel的公式:公式基本使用、单元格地址引用、错误值利用、追踪公式利用与追踪错误
  18. 拖拽插件jquery.dad.js
  19. 康耐视Visionpro白平衡的详细步骤
  20. 王者容易怎么开启语音服务器,王者荣耀怎么开语音?王者荣耀语音开启教程

热门文章

  1. IntelliJ IDEA 中的 project 和 module 与Eclipse中workspace和project的关系
  2. Problem 2238 Daxia Wzc's problem 1627 瞬间移动
  3. 【Matlab开发】MATLAB编译C/C++代码
  4. CSS自适应宽度圆角按钮
  5. unix mysql_Unix和Mysql中列出的数据库大小之间存在差异
  6. 在浏览器输入URL回车之后发生了什么
  7. KVM中virtio实现(九)
  8. vue--为什么data属性必须是一个函数
  9. python3 日志检索异常抛出异常 raise KeyError(key),KeyError: 'formatters'
  10. 【原创】开源Math.NET基础数学类库使用(06)直接求解线性方程组