【C++】19.红黑树模拟实现 set 和 map

我们想要实现STL中的set和map,那么第一步就需要看一下库函数是如何实现的:
在这里插入图片描述
通过查看源代码我们发现两个容器都包含了stl_tree.h,因此我们猜测此头文件实现的是红黑树。
但是set和map很显然不是使用同一棵树实现的,那么STL库是怎么解决这个问题的呢?

我们发现在构造红黑树的value时map使用的是pair<Key,T>,而set使用的则是Key

在这里插入图片描述

但是为什么在rb_tree类的构造时,要传四个参数呢?
我们知道Value是数据域,那么为什么还有传递Key呢?这难道不是重复了吗?
剩下的两个参数又代表着什么意思呢?
接下来我们的任务就是解决上述的问题。

一、set 和 map 的插入

首先value在插入时非常完美,但是在查找和删除时我们又应如何操作呢?set实现时,可以通过Value来进行操作,但是map实现时,我们有应如何操作呢?提取first元素吗?这样的话传递一个Key类型来方便操作。
接下来我们来实现一下插入部分发现:

if (kv < cur->_kv)
{parent = cur;cur = cur->_left;
}

当我们进行到比较操作的修改时,这个数据如何比较呢?
set的话我们当然可以直接比较,但是map呢?
在这里插入图片描述
通过查阅我们发现不是仅仅按first比较,因此我们需要定义方法来解决这个问题。
我们如何按照我们所预想的情景比较呢?
这样的话我们可以定义一个类来取得想要比较的元素
在这里插入图片描述
因此插入部分代码修改如下:

bool Insert(const V& v)
{//根节点为空,那此时插入的节点就是新节点if (_root == nullptr){_root = new Node(v);_root->_col = Black;return true;}KeyOfV kov;//提取key//此时根节点不为空//开始找应该插入的位置Node* cur = _root;Node* parent = cur->_parent;while (cur){if (kov(v) <kov( cur->_v)){parent = cur;cur = cur->_left;}else if (kov(v) >kov( cur->_v)){parent = cur;cur = cur->_right;}elsereturn false;//相等就表示已经存在了}//插入新节点cur = new Node(v);if (kov(v)<kov( parent->_v))parent->_left = cur;elseparent->_right = cur;cur->_parent = parent;//红色才修改while (parent&&parent->_col == Red){//取得g节点和u节点Node* grandfather = parent->_parent;Node* uncle = nullptr;//父节点此时为左孩子if (parent == grandfather->_left){uncle = grandfather->_right;}//父节点此时为右孩子else{uncle = grandfather->_left;}//u节点为红色if (uncle && uncle->_col == Red){parent->_col = uncle->_col = Black;grandfather->_col = Red;cur = grandfather;parent = cur->_parent;}//u节点不存在或u节点为黑色else{//父节点是g的左孩子if (parent == grandfather->_left){//cur是父节点的左孩子if (cur == parent->_left){RotateR(grandfather);parent->_col = Black;grandfather->_col = Red;}//cur是父节点的右孩子else{RotateLR(grandfather);cur->_col = Black;grandfather->_col = Red;}break;//调整完此时一定ok}//父节点是g的右孩子else{//cur是父节点的左孩子if (cur == parent->_left){RotateRL(grandfather);cur->_col = Black;grandfather->_col = Red;}//cur是父节点的右孩子else{RotateL(grandfather);parent->_col = Black;grandfather->_col = Red;}break;}}}_root->_col = Black;return true;
}

二、set 和 map 迭代器实现遍历

我们通过查看源代码发现,map和set底层都是通过调用红黑树的迭代器来完成遍历的:
在这里插入图片描述
那么此时我们只需要关注红黑树的迭代器是怎么实现的即可。
在这里插入图片描述
而底层的红黑树实现是利用头结点:
在这里插入图片描述
我们没有设置头节点,因此在这里简单实现一下:

//红黑树迭代器
template<class V,class Ref,class Ptr>
struct RBTreeIterator
{typedef typename RBTreeNode<V>	Node;//节点typedef typename RBTreeIterator<V, Ref, Ptr> Self;Node* _node;Node* _root;RBTreeIterator(Node* node,Node* root) :_node(node),_root(root){}//++_nodeSelf& operator++(){Node* cur = _node;if (cur->_right ){Node* LeftMost = cur->_right;while (LeftMost->_left){LeftMost = LeftMost->_left;}_node = LeftMost;}else{Node* parent = cur->_parent;while (parent && parent->_right == cur){cur = parent;parent = cur->_parent;}_node = parent;}return *this;}//--_nodeSelf& operator--(){if (_node == nullptr){Node* RightMost = _root;while (RightMost->_right){RightMost = RightMost->_right;}_node = RightMost;}else{Node* cur = _node;if (cur->_left){Node* RightMost = cur->_left;while (RightMost->_right){RightMost = RightMost->_right;}_node = RightMost;}else{Node* parent = cur->_parent;while (parent && parent->_left == cur){cur = parent;parent = cur->_parent;}_node = parent;}}return *this;}Ref  operator*(){return _node->_v;}Ptr operator->(){return &_node->_v;}bool operator!=(const Self& s){return _node != s._node;}bool operator==(const Self& s){return _node == s._node;}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3267343.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

C# Nmodbus,EasyModbusTCP读写操作

Nmodbus读写 两个Button控件分别为 读取和写入 分别使用控件的点击方法 ①引用第三方《NModbus4》2.1.0版本 全局 public SerialPort port new SerialPort("COM2", 9600, Parity.None, 8, (StopBits)1); ModbusSerialMaster master; public Form1() port.Open();…

Beam Search 原理详解

文章目录 1. 前言2. 原理3. 举例4. 参考 1. 前言 Beam Search 是一种启发式图搜索算法&#xff0c;用于在图或树的搜索过程中寻找最有可能的路径。它常用于自然语言处理&#xff08;NLP&#xff09;中的序列生成任务&#xff0c;如机器翻译、语音识别和文本生成等。与穷举搜索…

渲染技术如何帮助设计内容实现从平面到立体的转换

随着数字艺术和视觉特效的飞速发展&#xff0c;三维建模与渲染技术在影视、游戏、广告、工业设计、建筑可视化等多个领域展现出了其不可或缺的重要性。这一技术不仅实现了从平面到立体的跨越&#xff0c;还极大地丰富了视觉表达的层次感和真实感。 三维建模&#xff1a;构建虚…

一站式企业服务平台有哪些特点和优势!

随着我国经济的快速发展&#xff0c;各地方政府及产业园区为了能够吸引投资和优质企业入驻&#xff0c;纷纷在营商环境优化上大下功夫&#xff0c;这是因为当下企业已经不再满足于基础服务&#xff0c;而是更看重利于企业发展的软环境&#xff0c;随之建设“一站式企业服务平台…

flex/lex使用和学习

flex/lex用于生成解析配置文件的C代码&#xff0c;我们可以不用自己手动去做解析的工作&#xff0c;交由他们生成的代码去做。 假设&#xff0c;我有如下一个配置文件config.xml 配置文件中定义了三种channel,分别为SSIF, IPMB, NET&#xff0c;每一种channel都有4个int属性&a…

PyTorch基础(24)--torch.multinomial()方法

&#x1f449;torch.multinomial的源码见https://github.com/dongjinkun/PyTorch/tree/main/torch 一、前言 torch.multinomial()方法多出现在需要采样的场景中&#xff0c;如强化学习。具体讲&#xff0c;当使用强化学习解决旅行商问题时&#xff0c;针对某一个instance&…

项目实战——外挂开发(30小时精通C++和外挂实战)

项目实战——外挂开发&#xff08;30小时精通C和外挂实战&#xff09; 外挂开发1-监控游戏外挂开发2-秒杀僵尸外挂开发3-阳光地址分析外挂开发4-模拟阳光外挂开发5-无限阳光 外挂开发1-监控游戏 外挂的本质 有两种方式 1&#xff0c;修改内存中的数据 2&#xff0c;更改内存中…

外文文献去哪个网站查找下载又快又准

今天收到好多同学的文献求助&#xff0c;大部分都是外文文献。那么外文文献去哪里查找下载比较好呢&#xff1f;本文小编就讲解一下自己平时是在什么网站上查找获取文献的&#xff0c;下面就用几篇求助文献演示一下获取过程&#xff1a; 第一篇、OVID数据库&#xff1a;A Crit…

录音教程分享:电脑在线录音,7款录音软件免费版公开!

在我们的日常生活中&#xff0c;不可避免地会遇到需要在电脑上录制各种系统内音频的场景。无论是记录一次讲座、一段对话&#xff0c;或者录制某个重要网站上的音频&#xff0c;这种需求变得愈发重要且广泛。然而&#xff0c;对许多人来说&#xff0c;在电脑上在线录音可能是一…

菜鸟从0学微服务——MyBatis-Plus

关于“菜鸟从0学微服务” 针对有编程基础&#xff0c;开始学习微服务的同学&#xff0c;我们陆续推出从0学微服务的笔记分享。力求从各个中间件的使用来反思这些中间件的作用和优势。 会分享的比较快&#xff0c;会记录demo演算和中间件的使用过程&#xff0c;至于细节的理论…

Spark_Oracle_II_Spark高效处理Oracle时间数据:通过JDBC桥接大数据与数据库的分析之旅

接前文背景&#xff0c; 当需要从关系型数据库&#xff08;如Oracle&#xff09;中读取数据时&#xff0c;Spark提供了JDBC连接功能&#xff0c;允许我们轻松地将数据从Oracle等数据库导入到Spark DataFrame中。然而&#xff0c;在处理时间字段时&#xff0c;可能会遇到一些挑战…

计算机网络知识-面试点1

1. 三握四挥 定义&#xff1a; 在计算机网络中&#xff0c;特别是TCP/IP协议中&#xff0c;“三握”指的是三次握手&#xff08;Three-way Handshake&#xff09;&#xff0c;而“四挥”则指的是四次挥手&#xff08;Four-way Handshake&#xff09;。这两个过程分别用于TCP连接…

模式Hash和history

vuerouter有两种路由模式Hash和history。区别&#xff1a;Hash为默认模式&#xff0c;url中包含一个#符号的哈希部分。优势&#xff1a;兼容性好&#xff0c;不需要后端服务器的特殊配置。缺点&#xff1a;不够美观&#xff0c;搜索引擎优化较差。History模式使用的浏览器的His…

多模态大模型应用中的Q-Former是什么?

多模态大模型应用中的Q-Former是什么&#xff1f; Q-Former是一种新型的神经网络架构&#xff0c;专注于通过查询&#xff08;Query&#xff09;机制来改进信息检索和表示学习。在这篇博客中&#xff0c;我们将详细探讨Q-Former的工作原理、应用场景&#xff0c;并在必要时通过…

leetcode日记(55)二进制求和

将短的字符串前面补充0&#xff0c;使两字符串对其再进行加法&#xff1a; class Solution { public:string addBinary(string a, string b) {int na.size();int mb.size();if(n>m) b.insert(0,n-m,0);else if(m>n) a.insert(0,m-n,0);string c;int jw0;for(int imax(n,…

【C++指南】类和对象(上)

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《数据结构与算法》 期待您的关注

PostgreSQL的pg-collector工具

PostgreSQL的pg-collector工具 pg-collector 是一个用于 PostgreSQL 数据库的监控和数据收集工具。它主要用于收集 PostgreSQL 实例的性能指标、查询统计和日志信息&#xff0c;以便进行数据库性能分析和故障排查。通过收集这些数据&#xff0c;管理员可以更好地了解数据库的运…

减少 95% 资源的向量搜索 | 使用云搜索的 DiskANN

当前尖端的向量近邻搜索算法&#xff0c;主要以图搜索算法为主&#xff0c;此类算法为了能够最大化搜索的速度与准确度&#xff0c;需要将对应的索引结构和原始数据存放在内存中&#xff0c;显然这不仅大大提高了成本&#xff0c;还限制了数据集的大小。例如在当前主流的内存型…

快递员工告诉你,寄快递如何薅羊毛(知道这个方法,立省好几百)

谁能想象自从去了快递公司上班后&#xff0c;知道了一个惊人的内幕&#xff01;&#xff01;现在发快递和大件的&#xff0c;全国不管寄到哪都才只要5块钱呢&#xff01;&#xff01; 上门取件不说&#xff0c;不管寄多少快递&#xff0c;寄到哪里&#xff0c;仅是原价的5折。 …

MongoDB教程(二十):MongoDB正则表达式

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 引言一、正则表…