STL深度剖析2

rb_tree深度探索

rb_tree vs AVL树

  • AVL是一个高度平衡的二叉树,而红黑树不是
  • 红黑树每次插入一个元素,最多只需要两次旋转;而AVL可能需要更多次平衡操作
  • 搜索速度:AVL树更加快,因为其严格遵守高度平衡,搜索查找的平均时间复杂度为log2(n)
  • 插入速度:红黑树更加快,因为最多只需要两次旋转再加一些重新着色。
  • AVL树是rb_tree的子集

红黑树的结构

  • 红黑树是平衡二分搜索树中常常使用的一种,平衡二分搜索树的特性:排列规则有利search和insert,并保持适度平衡。

  • 红黑树提供遍历的功能及iterators。按正常规则(++ite)遍历,便能获得排序状态。

  • 红黑树的结构样例:

  • 为红黑树的中序遍历,begin()在左下,end()是在右下

  • 红黑树的规则(首先需要是一颗二分查找树{BST}):

    • 1.每个节点不是红色就是黑色
    • 2.根节点为黑色
    • 3.如果节点为红,其子节点必须是黑(如果节点为黑,其子节点既可以是红也可以是黑)
    • 4.任一节点至NULL(树尾端)的任何路径,所含黑色节点数必须相同
  • 根据规则4,新增节点必须为红;根据规则3,新增节点之父节点必须为黑,当新节点根据二叉搜索树的规则到达其插入点, 但未能符合上述要求,就必须调整颜色并旋转树形

  • 我们不应该用红黑树的iterators改变元素值(因为元素有其严谨的排序规则)。但是编程层面并未阻止此事,rb_tree将会为set和map服务,而map允许元素的data被改变, 只有元素的key才是不能被改变的。

  • rb_tree提供两种insertion操作(红黑树本身对重复与否没有限制,而取决于insert的方式):insert_unique()和insert_equal()。前者表示节点的key一定在整个树中独一无二, 否则安插失败;后者表示节点的key可以重复。

部分源码(在这里将key和data合起来的节点合成value):

cpp 复制代码
//这里的Value是key和data的组合,如果value只传一个值说明没有value(set)
template <class Key, class Value, class KeyOfValue, class Compare,
          class Alloc = alloc>
class rb_tree {
protected:
    typedef __rb_tree_node<Value> rb_tree_node;//红黑树的结构
    ···
public:
     // 注意,没有定义iterator(喔,不,定义在后面)
    typedef rb_tree_node* link_type;//指向红黑树节点的指针
    ···
protected:
    //rb_tree只以三个资料表现它自己
    size_type node_count;//rb_tree的大小(节点数量)
    link_type header;
    Compare key_compare;//key的大小比较准则;应会是个function object
    ···
}

红黑树插入节点

红黑树插入的节点默认为红色,首先根据二叉树寻找插入的位置,再根据相对位置来调整红色和黑色,以及旋转的问题。

关于红黑树的插入问题,可以在这个网站 来手动插入试验一下!(Red/Black Tree Visualization)

  • 关于红色和黑色节点的问题:
    • 插入节点初始一定为红色,新增节点的父节点必须为黑色,再根据rb_tree的四条规则进行调整。
  • 关于旋转,先看一个实例:

红黑树旋转的具体规则如下(假设插入的节点为X):

  1. 将新插入的节点标记为红色
  2. 如果 X 是根结点(root),则标记为黑色(2⃣️)
  3. 如果 X 的 parent 不是黑色,同时 X 也不是 root(3⃣️):
    • 如果 X 的 uncle (叔叔) 是红色:
      1. 将 parent 和 uncle 标记为黑色
      2. 将 grand parent (祖父) 标记为红色
      3. 让 X 节点的颜色与 X 祖父的颜色相同,然后重复步骤2⃣️3⃣️

。。。STL_sourcecode/10.第十讲 at master · caixiongjiang/STL_sourcecode

Set,multiset剖析

set和multiset特性

  • set/multiset以红黑树为底层结构,因此有自动排序的特性,排序的依据是key,而set和multiset的value和key 是合二为一的:value就是key(key和data合成value)
  • set和multiset提供遍历的操作以及iterator,按照正常的规则遍历就能获得排序状态。
  • 无法使用iterator来改变元素值(底层为将iterator设为const),因为key有其严谨的排序规则。
  • set的key必须独一无二,因此其insert()用的是rb_tree的insert_unique()
  • multiset元素的key可以重复,因此其insert()用的是rb_tree的insert_equal()

multiset容器

除了multiset之外和set基本没有区别

map和multimap特性

  • rb_tree为底层结构,因此有元素自动排序功能,排序的依据依然为key
  • 提供iterator,正常遍历便能获得排序状态的结果
  • 无法使用iterators来改变元素的key,但可以用来改变元素的data。(底层为将key值设为const类型)
  • map的key必须独一无二,因此其insert()用的是rb_tree的insert_unique()
  • multimap元素的key可以重复,因此其insert()用的是rb_tree的insert_equal()
map独特的operator\[\]
  • operator\[\]的作用为返回对应key的data值,如果这个key不存在,标准库将会自动创建该key值放入map中
  • 源码层:使用lower_bound来寻找元素的key值,如果找到则返回迭代器进行操作;如果没有找到则呼叫insert()
  • lower_bound是二分查找的一种版本,试图在已经排序的范围[first, last)中寻找一个元素值,如果找得到就返回 一个iterator指向其中的第一个符合条件的元素值;如果没有找到则返回last的iterator(最适合安插这个值的位置)
  • operator\[\]创建新的key比直接使用insert插入效率低,因为前面还多了一步lower_bound的过程

heap&priority_queue深入探索

STL_sourcecode/13.第十三讲 at master · caixiongjiang/STL_sourcecode

相关推荐
幻智星科技1 小时前
FPGA纯硬件UDP桥接:微秒级响应新范式
c++·fpga开发·硬件架构
数智奔流1 小时前
MiniMax的低价攻势,撞上“背题”疑云
前端·javascript·算法
青少儿编程课堂1 小时前
蓝桥杯·全国青少年信息素养大赛·电子学会Python/C++考级:位运算实战——二进制权限与最大异或解析
c++·python·算法·bfs·信息学竞赛
广州智造1 小时前
Radioss中破坏模型FAILTAB1的详细介绍
数据库·人工智能·算法·机器学习·仿真软件·radioss
青少儿编程课堂1 小时前
2026蓝桥杯青少组图形化真题:校园飞机大战解析(全国青少年信息素养·电子学会图形化考级)
c++·python·算法·bfs·信息学竞赛
周厉1 小时前
WebSocket 使用场景与实现方法:Java + Vue3 全栈实战
java·websocket·vue3·websocket双向通讯
wdfk_prog1 小时前
lwip教程 38:从 `lwipopts.h` 到 Port Contract——lwIP 裁剪、构建选择、OS Port 与 Network Port
java·开发语言
吹什么轩1 小时前
MySQL 内置函数全景:日期 / 字符串 / 数学 / 其他,一次讲透(附索引杀手排查)
java·数据库·面试
开开心心就好1 小时前
证件照排版打印工具,免费可自定义尺寸
服务器·开发语言·算法·随机森林·pdf·音视频·散列表