当前位置: 首页 > ai >正文

进阶数据结构:用红黑树实现封装map和set

嘿,各位技术潮人!好久不见甚是想念。生活就像一场奇妙冒险,而编程就是那把超酷的万能钥匙。此刻,阳光洒在键盘上,灵感在指尖跳跃,让我们抛开一切束缚,给平淡日子加点料,注入满满的
passion。准备好和我一起冲进代码的奇幻宇宙了吗?Let’s go!

请添加图片描述

我的博客:yuanManGan

我的专栏:C++入门小馆 C言雅韵集 数据结构漫游记 闲言碎语小记坊
进阶数据结构 走进Linux的世界 题山采玉 领略算法真谛

在这里插入图片描述


用红黑树实现封装map和set


实现步骤:

  1. 实现红黑树
  2. 封装 mapset 框架解决KeyOfT
  3. iterator
  4. const_iterator
  5. key不支持修改的问题
  6. operator[ ]

1.实现红黑树

上集我们已经实现了一个普通的红黑树 进阶数据结构:红黑树,


2.封装 map 和 set 框架解决KeyOfT


查看stl源码借鉴了解

发现实现 setmap 都包含了一个 tree 头文件,我们那篇博客实现的 key-value 的红黑树,那我们是不是要实现两个红黑树一个是 key 的一个 key-value 的呢?
stl中实现set和map所包含的头文件


不急我们看看源码:

template<typename _Key, typename _Val, typename _KeyOfValue,typename _Compare, typename _Alloc = allocator<_Val> >class _Rb_tree{}

我们凑凑这模板,这怎么又有key又有value那它怎么实现的set , set 不是不要value吗?


我来解释一下吧:

  • 可能写这个代码的程序员写的不太规范,这个地方的Val代表的不是我们之前写代码的value
  • 而是比如我们set传入的keymap传入的key_value,代表的是这一类,而不是单纯的value
  • 我们就这样形成了模板,本质上编译器还是写了两份代码,但增加了复用,减少了我们自己写。

那又有人问了,那我们不是只要一个模板参数就够了吗,为什么前面还得加个key呢?

  • 我们实现 find 等功能的时候需要使用到 key,所以不能偷懒

更改我们的红黑树

我们写就写的规范一点,我们将 V 替换为 T

//原本
////////////////////////////////////////////////////////////////
template <class K,class V>
struct RBTreeNode
{pair<K, V> _kv;RBTreeNode<K, V>* _parent;RBTreeNode<K, V>* _left;RBTreeNode<K, V>* _right;Colour _col;RBTreeNode(const pair<K, V>& kv): _kv(kv), _parent(nullptr), _left(nullptr), _right(nullptr)  // 按声明顺序放在_col之前, _col(RED){}
};
template <class K, class V>
class RBTree
{typedef RBTreeNode<K, V> Node;
public://...
private:Node* _root = nullptr;
};
////////////////////////////////////////////////////////////////
//修改后
template <class T>
struct RBTreeNode
{T _data;RBTreeNode<T>* _parent;RBTreeNode<V>* _left;RBTreeNode<V>* _right;Colour _col;RBTreeNode(T& data): _data(data), _parent(nullptr), _left(nullptr), _right(nullptr)  // 按声明顺序放在_col之前, _col(RED){}
};
template <class K, class T>
class RBTree
{typedef RBTreeNode<K, T> Node;
public://...
private:Node* _root = nullptr;
};

我们在修改 Insert 这个函数的时候就遇到的问题,我们怎么比较插入节点与原节点的大小呢?

  • 我们可以引入一个模板参数 KeyOfT 分别在 setmap头文件里面重载 ( ) 实现比较逻辑,如果是set就直接返回 keymap就返回kv中的 first

//set.h
template<class K>
class set
{struct SetKeyOfT{const K& operator()(const K& key){return key;}};
public://...
private:RBTree<K, K, SetKeyOfT> _t;	
};
//map.h
template<class K, class V>
class map
{struct MapKeyOfT{const K& operator()(const pair<K, V>& kv){return kv.first;}};
public://...
private:RBTree<K, pair<K, V>, MapKeyOfT> _t;	
};
  • insert
KeyOfT kot;
bool Insert(const T& data)
{//插入//空树if (_root == nullptr){_root = new Node(data);_root->_col = BLACK;return true;}Node* cur = _root;Node* parent = nullptr;while (cur){if (kot(data) > kot(cur->_data)){parent = cur;cur = cur->_right;}else if (kot(data) < kot(cur->_data)){parent = cur;cur = cur->_left;}else {return false;}}cur = new Node(data);cur->_col = RED;if (kot(data) > kot(parent->_data)){//是p的右子树parent->_right = cur;}else{//是p的左子树parent->_left = cur;}cur->_parent = parent;//变色while (parent && parent->_col == RED){Node* grandfather = parent->_parent;if (grandfather->_left == parent){Node* uncle = grandfather->_right;//u存在且为红if (uncle && uncle->_col == RED){//变色parent->_col = uncle->_col = BLACK;grandfather->_col = RED;//继续往上处理cur = grandfather;parent = cur->_parent;}else{//u存在但为黑if (cur == parent->_left){//c在左//     g           p  //   p   u --->  c   g// c                   uRotateR(grandfather);grandfather->_col = RED;parent->_col = BLACK;}else{//c在右//     g    RotateL(p)        g    RotateR(g)    c//  p     u ----------->   c     u -------->  p     g//     c                 p                             u      RotateL(parent);RotateR(grandfather);cur->_col = BLACK;grandfather->_col = RED;}break;}}else{Node* uncle = grandfather->_left;//u存在且为红if (uncle && uncle->_col == RED){//变色parent->_col = uncle->_col = BLACK;grandfather->_col = RED;//继续往上处理cur = grandfather;parent = cur->_parent;}else{//u存在但为黑if (cur == parent->_right){//c在右//     g           p  //   u   p --->  g   c//         c   uRotateL(grandfather);grandfather->_col = RED;parent->_col = BLACK;}else{//c在z左//     g    RotateR(p)      g    RotateL(g)    c//  u     p -----------> u     c -------->  g     p//     c                        p        u      RotateR(parent);RotateL
http://www.xdnf.cn/news/16270.html

相关文章:

  • 学习嵌入式的第三十一天-数据结构-(2025.7.23)网络协议封装
  • 数据中心-时序数据库InfluxDB
  • 掌握Gemini-2.5:现代AI开发中实用应用的综合指南
  • 二次函数图像动画展示
  • 在Power Automate Desktop中执行PowerShell获取SharePoint online某个文件夹的用户权限列表
  • excel删除重复项场景
  • 算法竞赛阶段二-数据结构(35)数据结构单链表模拟实现
  • Node.js 模拟 Linux 环境
  • 【每天一个知识点】GAN(生成对抗网络,Generative Adversarial Network)
  • Whisper语音转文字
  • 【洛谷】单向链表、队列安排、约瑟夫问题(list相关算法题)
  • 互联网应用主流框架整合 Spring Boot开发
  • Linux DNS 服务器正反向解析
  • 【IMMCKF】基于容积卡尔曼滤波(CKF)的多模型交互的定位程序,模型为CV和CT,三维环境,matlab代码|附下载链接
  • Nestjs框架: 基于Mongodb的多租户功能集成和优化
  • 算子推理是什么
  • 电脑开机后网络连接慢?
  • (Python)文件储存的认识,文件路径(文件储存基础教程)(Windows系统文件路径)(基础教程)
  • 【17】C# 窗体应用WinForm ——【文本框TextBox、富文本框RichTextBox 】属性、方法、实例应用
  • C++:list(2)list的模拟实现
  • Java中配置两个r2db连接不同的数据库
  • JavaScript:现代Web开发的核心动力
  • Mistral AI开源 Magistral-Small-2507
  • C++查询mysql数据
  • Codeforces Round 181 (Rated for Div. 2)
  • Bert项目--新闻标题文本分类
  • DAY31 整数矩阵及其运算
  • 告别镜像拉取慢!CNB无痛加速方案,一键起飞
  • [论文阅读] 人工智能 + 软件工程 | NoCode-bench:评估LLM无代码功能添加能力的新基准
  • JVM常见工具