C++ 学习日志 · 红黑树

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: C++ 学习日志 · 红黑树

红黑树:

红黑树 就和他的名字一样,树中只存在两种颜色的节点,他的本质也是一种二叉搜索树,它相对于使用平衡因子控制的二叉树,它会稍微宽松一些,控制平衡因子绝对值不超过1会比较严格也就意味着会有更多的旋转


红黑树的性质:

       ① 根节点是黑色

        ② 没有连续的红节点,红节点下一个节点必是黑节点

        ③ 每个节点的每条路径的都有相同数量的黑色节点

    ④ 每个叶子节点(空节点)都是黑色节点

综合以上的性质,可以得出新的性质:

       最长路径的节点个数不会超过最短路径的节点个数二倍

  最短路径:全是黑色节点

       最长路径:一黑一红交叉


模拟红黑树(三叉链):

insert:

红黑树和平衡二叉树相比,没有平衡二叉树那么严格,旋转的更少,但是既然要插入一个值,它的位置是可以根据子节点 左小右大 来确定,那它的颜色该如何选择呢?

       颜色的选择就要回归到红黑的性质(规则)上面

       如果插入的是红色节点,那么有可能破坏第②个规则

       如果插入的是黑色节点,那么就一定会破坏第③个规则,这样涉及新增节点的路径上的黑色

节点数量就会比其他的路径的黑色节点数量多一个

综上得出结论:插入的节点得是一个红色节点。 (毕竟这样我们还能"补救")

c6bfe2b5d76441cd9664932244e9921b.jpg

那大家看现在这种情况应该怎么调整颜色呢?

       调整颜色的同时也需要不破坏红黑树的规则:

       首先保证没有连续的红色节点,那么那么新节点的父亲节点就需要变成黑色,此时路径上的黑色节点的数量不统一,那么叔叔节点也应该变成黑色,

此时,最上面的爷爷节点,就要判断是否是根节点,如果是根节点则为黑色(规则第一条),不是则变为红色继续向上遍历   (如果此时爷爷不是根节点还保持黑色不变的话,那么图片中这一小的分支路径上面就会多出来一个节点)

e1065e4dfb6e4d1ea2c4c567e265abe0.jpg

bool insert(const pair<K, V>& data)
  {
    if (_root == nullptr)
    {
      _root = new node(data);
      _root->col = BLACK;
      return;
    }
    node* parent = nullptr;
    node* cur = _root;
    while (cur)
    {
      if (cur->_key > data)
      {
        parent = cur;
        cur = cur->_left;
      }
      else if (cur->_key < data)
      {
        parent = cur;
        cur = cur->_right;
      }
      else
      {
        return false;
      }
    }
    //插入新节点
    node* NewNode = new node(data);
    if (parent->_key > data)
    {
      parent->_left = NewNode;
    }
    else
    {
      parent->_right = NewNode;
    }
    cur = NewNode;
    while (parent && parent->col == RED)
    {
      node* groundnode = parent->_parent;
      if (groundnode->_left == parent)
      {
        node* unclenode = groundnode->_right;
        if (unclenode && unclenode == RED)
        {
          parent->col = unclenode->col = BLACK;
          groundnode->col = RED;
          cur = groundnode;
          parent = cur->_parent;
        }
      }
      else
      {
        node* unclenode = groundnode->_left;
      }
    }
  }

注意:颜色变化根子节点是父节点的左右没有关系

之前讨论的是叔叔节点存在且为黑的情况,那如果现在叔叔节点不存在呢

b5bbe071c5d54f32aeb440fa08dabbc5.jpg

这个时候就需要进行旋转了

2f8a4d21792c468486248b39417c831e.gif

注意:这个菱形代表的子节点的多种情况


现在如果叔叔节点,存在并且是黑色的呢?

4fb2d2c4a5124d98b606d7c0f306216a.jpg大家看这张图,就能明白有的时候一种情况,多数是由其他情况在调整的时候演变出来的上图就是叔叔节点存在且为黑的情况,那么此时应该怎么做呢?

c34d4cc799a64b90931d0df344ec90c9.gif

a462542fe31a46349eaeb1d80023f8ec.jpg

当然这个是右单旋(儿子节点、父亲节点它俩都是各自父亲节点的左节点),左单选的原理和这个是一样的.

bool insert(const pair<K, V>& data)
  {
    if (_root == nullptr)
    {
      _root = new node(data);
      _root->col = BLACK;
      return;
    }
    node* parent = nullptr;
    node* cur = _root;
    while (cur)
    {
      if (cur->_key > data)
      {
        parent = cur;
        cur = cur->_left;
      }
      else if (cur->_key < data)
      {
        parent = cur;
        cur = cur->_right;
      }
      else
      {
        return false;
      }
    }
    //插入新节点
    node* NewNode = new node(data);
    if (parent->_key > data)
    {
      parent->_left = NewNode;
    }
    else
    {
      parent->_right = NewNode;
    }
    cur = NewNode;
    while (parent && parent->col == RED)
    {
      node* groundnode = parent->_parent;
      if (groundnode->_left == parent)
      {
        node* unclenode = groundnode->_right;
        if (unclenode && unclenode == RED)
        {
          parent->col = unclenode->col = BLACK;
          groundnode->col = RED;
          cur = groundnode;
          parent = cur->_parent;
        }
        else
        {
          if (parent->_left == cur)
          {
            RotateR(groundnode);
            parent->col = BLACK;
            groundnode->col = RED;
          }
          else
          {
            RtotateL(parent);
            RtotateR(groundnode);
            cur->col = BLACK;
            groundnode->col = RED;
          }
          break;
        }
      }
      else
      {
        node* unclenode = groundnode->_left;
        if (unclenode && unclenode == RED)
        {
          parent->col = unclenode->col = BLACK;
          groundnode->col = RED;
          cur = groundnode;
          parent = cur->_parent;
        }
        else
        {
          if (parent->_right == cur)
          {
            RotateL(groundnode);
            parent->col = BLACK;
            groundnode->col = RED;
          }
          else
          {
            RtotateR(parent);
            RtotateL(groundnode);
            cur->col = BLACK;
            groundnode->col = RED;
          }
          break;
        }
      }
    }
  }


相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
目录
相关文章
|
6天前
|
存储 缓存 监控
用 C++ 红黑树给公司电脑监控软件的日志快速排序的方法
本文介绍基于C++红黑树算法实现公司监控电脑软件的日志高效管理,利用其自平衡特性提升日志排序、检索与动态更新效率,并结合实际场景提出优化方向,增强系统性能与稳定性。
23 4
|
6月前
|
编译器 C++ 容器
【c++丨STL】基于红黑树模拟实现set和map(附源码)
本文基于红黑树的实现,模拟了STL中的`set`和`map`容器。通过封装同一棵红黑树并进行适配修改,实现了两种容器的功能。主要步骤包括:1) 修改红黑树节点结构以支持不同数据类型;2) 使用仿函数适配键值比较逻辑;3) 实现双向迭代器支持遍历操作;4) 封装`insert`、`find`等接口,并为`map`实现`operator[]`。最终,通过测试代码验证了功能的正确性。此实现减少了代码冗余,展示了模板与仿函数的强大灵活性。
174 2
|
3月前
|
存储 C++
c++ 红黑树(带头结点)(k,k型)
想必在看到这篇文章的时候,你一定是带着问题去搜索的,一定是对红黑树已经有了初步大致的认识,已经知道了红黑树的性质与普通红黑树的功能与如何代码实现,但是莫一天突然看到了带头结点的红黑树,肯定是对此有一些疑惑的,或者来说在代码的实现上自己存在着某些疑惑。那么话不多说,就先给出红黑树(带头结点)的完整实现代码。然后再给出相应的详细解释。
82 0
|
3月前
|
Java C++
c++ 红黑树(自平衡二叉搜索树)(k,v型)
因为红黑树是一种特殊的AVL树(但少了平衡因子的存在),所以其结点的定义是在AVL树上加上新的成员变量,用于表示结点的颜色。RED,BLACK,//三叉链, _kv(kv){}首先我们在默认构造上,默认构造结点的颜色默认情况下为红色所以为什么构造结点时,默认将结点的颜色设置为红色?这是因为:当我们向红黑树插入结点时,若我们插入的是黑色结点,那么插入路径上黑色结点的数目就比其他路径上黑色结点的数目多了一个,即破坏了红黑树的性质4,此时我们就需要对红黑树进行调整。
97 0
|
5月前
|
调度
FreeRTOS学习日志 - 第一天
这就是我的FreeRTOS学习日志 - 第一天的内容,明天继续探索这片实时操作系统的广阔海洋。+
97 12
|
8月前
|
C++ 开发者
C++学习之继承
通过继承,C++可以实现代码重用、扩展类的功能并支持多态性。理解继承的类型、重写与重载、多重继承及其相关问题,对于掌握C++面向对象编程至关重要。希望本文能为您的C++学习和开发提供实用的指导。
135 16
|
9月前
|
算法 网络安全 区块链
2023/11/10学习记录-C/C++对称分组加密DES
本文介绍了对称分组加密的常见算法(如DES、3DES、AES和国密SM4)及其应用场景,包括文件和视频加密、比特币私钥加密、消息和配置项加密及SSL通信加密。文章还详细展示了如何使用异或实现一个简易的对称加密算法,并通过示例代码演示了DES算法在ECB和CBC模式下的加密和解密过程,以及如何封装DES实现CBC和ECB的PKCS7Padding分块填充。
192 4
2023/11/10学习记录-C/C++对称分组加密DES
|
9月前
|
存储 算法 安全
基于红黑树的局域网上网行为控制C++ 算法解析
在当今网络环境中,局域网上网行为控制对企业和学校至关重要。本文探讨了一种基于红黑树数据结构的高效算法,用于管理用户的上网行为,如IP地址、上网时长、访问网站类别和流量使用情况。通过红黑树的自平衡特性,确保了高效的查找、插入和删除操作。文中提供了C++代码示例,展示了如何实现该算法,并强调其在网络管理中的应用价值。
|
10月前
|
存储 C++
【C++】红黑树
红黑树是一种自平衡二叉搜索树,通过节点颜色(红或黑)及特定规则维持平衡,确保操作效率。其性质包括:每个节点非红即黑,根节点必黑,红节点的子节点必黑,从任一节点到其每个叶子的所有路径含相同数量的黑节点。实现上,通过节点结构定义、基本操作(插入、删除、旋转等)、维护平衡性质等步骤完成。代码示例展示了节点定义、插入操作及旋转调整方法。
156 2
【C++】红黑树
|
11月前
|
编译器 C语言 C++
配置C++的学习环境
【10月更文挑战第18天】如果想要学习C++语言,那就需要配置必要的环境和相关的软件,才可以帮助自己更好的掌握语法知识。 一、本地环境设置 如果您想要设置 C++ 语言环境,您需要确保电脑上有以下两款可用的软件,文本编辑器和 C++ 编译器。 二、文本编辑器 通过编辑器创建的文件通常称为源文件,源文件包含程序源代码。 C++ 程序的源文件通常使用扩展名 .cpp、.cp 或 .c。 在开始编程之前,请确保您有一个文本编辑器,且有足够的经验来编写一个计算机程序,然后把它保存在一个文件中,编译并执行它。 Visual Studio Code:虽然它是一个通用的文本编辑器,但它有很多插
363 6