c++ - 模拟实现set、map
文章目录
- 前言
- 一、set模拟实现
- 二、map模拟实现
前言
在C++标准库中,std::set 和 std::map都是非常常用的容器,它们提供了基于键值对的存储和快速查找能力。然而,关于它们的底层实现,C++标准并没有强制规定具体的数据结构,只是规定了它们的行为特性(如唯一性、有序性等)。不过,大多数C++标准库实现(如GCC的libstdc++和Clang的libc++)都采用了红黑树(Red-Black> Tree)作为std::set和std::map的底层数据结构。
下面都是基于红黑树实现的set和map。
一、set模拟实现
当前的红黑树需要这三个类型参数(键值、数据,通过数据求key的仿函数),这是为了map也能够复用,但是set只传入一个数据,所以采用这样的方式:<K, const K,Setfunc< K >>,因为set中的数据是不能被修改的所以在第二个类型中加上const
1、基本框架
//获取红黑树key的函数
template <class K>
struct Setfunc
{K operator()(const K& val){return val;}
};template <class K, class KeyOfValue = Setfunc<K>>
class set
{
public://红黑树typedef RBTree<K, const K, KeyOfValue> RB;private://红黑树RB _rbset;};
2、迭代器
这里的迭代器直接复用红黑树的迭代器。
/*
第一 K类型是作为键值给删除,查找等需要键值的接口使用的
第二 const K是作为数据,给插入等接口使用
第三 KeyOfValue是仿函数,是给红黑树将数据类型转化为key使用,如插入时使用
*/
//迭代器
typedef typename RBTree<K,const K, KeyOfValue>::Iterator iterator;
typedef typename RBTree<K, const K, KeyOfValue>::ConstIterator cosnt_iterator;//迭代器
iterator begin()
{return _rbset.Begin();
}iterator end()
{return _rbset.End();
}cosnt_iterator begin() const
{return _rbset.Begin();
}cosnt_iterator end() const
{return _rbset.End();
}
3、插入、删除、查找、清空
以上接口均复用红黑树接口
//插入
pair<bool, iterator> insert(const K & val)
{return _rbset.Insert(val);
}//删除
bool erase(const K& key)
{return _rbset.Erase(key);
}//查找
iterator find(const K& key)
{return _rbset.Find(key);
}//清空
bool clear()
{_rbset.Clear();
}
4、拷贝构造和赋值重载
(1)拷贝构造:
遍历需要拷贝的对象,再插入到新的对象里。
set(const set<K, KeyOfValue> & p)
{//遍历set,重新插入set<K, KeyOfValue>::cosnt_iterator it = p.begin();while (it != p.end()){insert(*it);++it;}
};
(2)赋值重载:
比拷贝构造多一步,就是在插入前需要清空。
set<K, KeyOfValue>& operator=(const set<K, KeyOfValue>& p)
{//清空当前setclear();//遍历set,重新插入set<K, KeyOfValue>::cosnt_iterator it = p.begin();while (it != p.end()){insert(*it);++it;}
}
5、测试
void test_set()
{set<int> _s;//插入for (int i = 0; i < 10; i++){_s.insert(i);}cout << "s1: ";set<int> s1 = _s; //拷贝构造//迭代器遍历set<int>::iterator it1 = s1.begin();while (it1 != s1.end()){cout << *it1 << " ";++it1;}cout << endl;cout << "s2: ";set<int> s2;s2 = s1; //赋值//删除s2.erase(1);s2.erase(5);s2.erase(4);s2.erase(8);//迭代器遍历set<int>::iterator it2 = s2.begin();while (it2 != s2.end()){cout << *it2 << " ";++it2;}cout << endl;
}

6、总代码
//获取红黑树key的函数
template <class K>
struct Setfunc
{K operator()(const K& val){return val;}
};template <class K, class KeyOfValue = Setfunc<K>>
class set
{
public://红黑树typedef RBTree<K, const K, KeyOfValue> RB;/*第一 K类型是作为键值给删除,查找等需要键值的接口使用的第二 const K是作为数据,给插入等接口使用第三 KeyOfValue是仿函数,是给红黑树将数据类型转化为key使用,如插入时使用*///迭代器typedef typename RBTree<K,const K, KeyOfValue>::Iterator iterator;typedef typename RBTree<K, const K, KeyOfValue>::ConstIterator cosnt_iterator;//构造set() {};set(const set<K, KeyOfValue> & p) {//遍历set,重新插入set<K, KeyOfValue>::cosnt_iterator it = p.begin();while (it != p.end()){insert(*it);++it;}};set<K, KeyOfValue>& operator=(const set<K, KeyOfValue>& p){//清空当前setclear();//遍历set,重新插入set<K, KeyOfValue>::cosnt_iterator it = p.begin();while (it != p.end()){insert(*it);++it;}return *this;}//析构~set() {};//迭代器iterator begin(){return _rbset.Begin();}iterator end(){return _rbset.End();}cosnt_iterator begin() const{return _rbset.Begin();}cosnt_iterator end() const{return _rbset.End();}//插入pair<bool, iterator> insert(const K & val){return _rbset.Insert(val);}//删除bool erase(const K& key){return _rbset.Erase(key);}//查找iterator find(const K& key){return _rbset.Find(key);}//清空void clear(){_rbset.Clear();}private://红黑树RB _rbset;
};
二、map模拟实现
map给红黑树传的类型为:<K, pair<const K, V, KeyOfValue> ,K类型用于删除、查找等,pair<const K, V,>作为数据插入,KeyOfValue取pair<const K, V,>中的K类型,又因为键值不能修改所以pair<const K, V,>中的K加上const修饰。
1、基础框架
//获取 pair<K,V>中的key
template <class K,class V>
struct Mapfunc
{K operator()(const pair<K,V>& val){return val.first;}
};template <class K, class V, class KeyOfValue = Mapfunc<K,V>>
class map
{
public://重命名typedef RBTree<K, pair<const K, V>, KeyOfValue> RB;
private://红黑树RB _rbmap;
};
2、迭代器
依旧是复用红黑树迭代器即可。
typedef typename RB::Iterator iterator;
typedef typename RB::ConstIterator const_iterator;iterator begin()
{return _rbmap.Begin();
}iterator end()
{return _rbmap.End();
}const_iterator begin() const
{return _rbmap.Begin();
}const_iterator end()const
{return _rbmap.End();
}
3、插入、删除、查找、清空
依旧是复用红黑树接口即可。
//插入
pair<bool,iterator> insert(const pair<K, V>& val)
{return _rbmap.Insert(val);
}//删除
bool erase(const K& key)
{return _rbmap.Erase(key);
}//查找
iterator find(const K& key)
{return _rbmap.Find(key);
}//清空
void clear()
{_rbmap.Clear();
}
4、重载[ ]
当key不存在时,重载[ ]就会用key进行插入操作并返回插入后key对应数据的引用(此时key对应数据是用其默认构造进行初始化的),当key存在时,返回key对应数据的引用。
//重载[]
V& operator[](const K& key)
{pair<bool, iterator> ret = insert(make_pair(key, V()));return ret.second->second;
}
5、拷贝构造和赋值构造
(1)遍历需要拷贝的对象并将其数据插入当前对象即可。
map(const map<K,V, KeyOfValue> & p)
{map<K, V, KeyOfValue>::const_iterator it = p.begin();while (it != p.end()){insert(*it);++it;}
};
(2)先清空再遍历插入当前对象即可。
map<K, V, KeyOfValue>& operator=(const map<K, V, KeyOfValue>& p)
{clear();map<K, V, KeyOfValue>::const_iterator it = p.begin();while (it != p.end()){insert(*it);++it;}return *this;
}
6、测试
void test_map()
{//默认构造map<int, int> m;//插入for(int i = 1; i < 10; i++)m.insert({ i,i });//迭代器遍历cout << "m1:";//拷贝构造map<int, int> m1 = m;map<int, int>::iterator it1 = m1.begin();while (it1 != m1.end()){cout << it1->second << " ";++it1;}cout << endl;cout << "m2:";//赋值map<int, int> m2;m2 = m;//删除m2.erase(1);m2.erase(2);//使用[]m2[3] = 100;m2[4] = 100;map<int, int>::iterator it2 = m2.begin();while (it2 != m2.end()){cout << it2->second << " ";++it2;}}

7、总代码
template <class K,class V>
struct Mapfunc
{K operator()(const pair<K,V>& val){return val.first;}
};
template <class K, class V, class KeyOfValue = Mapfunc<K,V>>
class map
{
public:typedef RBTree<K, pair<const K, V>, KeyOfValue> RB;typedef typename RB::Iterator iterator;typedef typename RB::ConstIterator const_iterator;map() {};~map() {};map(const map<K,V, KeyOfValue> & p) {map<K, V, KeyOfValue>::const_iterator it = p.begin();while (it != p.end()){insert(*it);++it;}};map<K, V, KeyOfValue>& operator=(const map<K, V, KeyOfValue>& p){clear();map<K, V, KeyOfValue>::const_iterator it = p.begin();while (it != p.end()){insert(*it);++it;}return *this;}//迭代器iterator begin(){return _rbmap.Begin();}iterator end(){return _rbmap.End();}const_iterator begin() const {return _rbmap.Begin();}const_iterator end()const {return _rbmap.End();}//插入pair<bool,iterator> insert(const pair<K, V>& val){return _rbmap.Insert(val);}//删除bool erase(const K& key){return _rbmap.Erase(key);}//查找iterator find(const K& key){return _rbmap.Find(key);}//重载[]V& operator[](const K& key){pair<bool, iterator> ret = insert(make_pair(key, V()));return ret.second->second;}//清空void clear(){_rbmap.Clear();}private:RB _rbmap;
};
相关文章:
c++ - 模拟实现set、map
文章目录 前言一、set模拟实现二、map模拟实现 前言 在C标准库中,std::set 和 std::map都是非常常用的容器,它们提供了基于键值对的存储和快速查找能力。然而,关于它们的底层实现,C标准并没有强制规定具体的数据结构,只…...
计算机网络-PIM协议基础概念
一、PIM基础概念 组播网络回顾: 组播网络从网络结构上大体可以分为三个部分: 源端网络:将组播源产生的组播数据发送至组播网络。 组播转发网络:形成无环的组播转发路径,该转发路径也被称为组播分发树(Multi…...
优化PyCharm:让IDE响应速度飞起来
优化PyCharm:让IDE响应速度飞起来 PyCharm,作为一款功能强大的集成开发环境(IDE),在提供丰富功能的同时,有时也会出现响应慢的问题。这不仅影响开发效率,还可能打击开发者的积极性。本文将详细…...
对象转化为String,String转化为对象
title: 对象转化为string,string转化为对象 date: 2024-08-02 11:50:40 tags: javascript const obj { uname:haha, age:18,gender:女} //将对象转换成string JSON.stringify(obj) //取成一个对象,将字符串传化为对象 JSON.parse(obj)常用领域在localst…...
SolverLearner:提升大模型在高度归纳推理的复杂任务性能,使其能够在较少的人为干预下自主学习和适应
SolverLearner:提升大模型在高度归纳推理的复杂任务性能,使其能够在较少的人为干预下自主学习和适应 提出背景归纳推理(Inductive Reasoning)演绎推理(Deductive Reasoning)反事实推理(Counterf…...
PHP智能问诊导诊平台-计算机毕业设计源码75056
摘 要 智能问诊导诊平台作为一种智能化医疗服务工具,利用PHP语言开发,旨在为用户提供便捷的在线问诊和导诊服务。该平台集成了智能算法和医疗数据,实现了智能化的病情诊断和治疗建议,帮助用户更快速地获取医疗信息和建议。用户可…...
数据结构初阶(c语言)-排序算法
数据结构初阶我们需要了解掌握的几种排序算法(除了直接选择排序,这个原因我们后面介绍的时候会解释)如下: 其中的堆排序与冒泡排序我们在之前的文章中已经详细介绍过并对堆排序进行了一定的复杂度分析,所以这里我们不再过多介绍。 一&#x…...
网络云相册实现--nodejs后端+vue3前端
目录 主页面 功能简介 系统简介 api 数据库表结构 代码目录 运行命令 主要代码 server apis.js encry.js mysql.js upload.js client3 index.js 完整代码 主页面 功能简介 多用户系统,用户可以在系统中注册、登录及管理自己的账号、相册及照片。 每…...
【JS】Object.defineProperty与Proxy
一、Object.defineProperty 这里只是简单描述,具体请看另一篇文章:Object.defineProperty。 Object.defineProperty 是 JavaScript 中用于定义或修改对象属性的功能强大的方法。它可以精确地控制属性的行为,如是否可枚举、可配置、可写等。…...
《计算机网络》(第8版)第8章 互联网上的音频/视频服务 复习笔记
第 8 章 互联网上的音频/视频服务 一、概述 1 多媒体信息的特点 多媒体信息(包括声音和图像信息)最主要的两个特点如下: (1)多媒体信息的信息量往往很大; (2)在传输多媒体数据时&a…...
linux进程控制——进程替换——exec函数接口
前言: 本节内容进入linux进程控制板块的最后一个知识点——进程替换。 通过本板块的学习, 我们了解了进程的基本控制方法——进程创建, 进程退出, 进程终止, 进程替换。 进程控制章节和上一节进程概念板块都是在谈进程…...
Apache解析漏洞~CVE-2017-15715漏洞分析
Apache解析漏洞 漏洞原理 # Apache HTTPD 支持一个文件拥有多个后缀,并为不同后缀执行不同的指令。比如如下配置文件: AddType text/html .html AddLanguage zh-CN .cn# 其给 .html 后缀增加了 media-type ,值为 text/html ;给 …...
Xilinx管脚验证流程及常见问题
1 流程 1.1 新建I/O Planning Project I/O Planning Project中可以不需要RTL的top层.v代码,仅图形化界面即可配置管脚约束XDC文件的生成: Create I/O Ports: 导出XDC文件和自动生成的top_interface.v文件: 1.2 新建test Project …...
格雷厄姆的《聪明的投资者》被誉为“投资圣经”
本杰明格雷厄姆的《聪明的投资者》(The Intelligent Investor: A Book of Practical Counsel)是投资领域的一部经典之作,被誉为“投资圣经”。以下是对该书的详细解析: 一、书籍基本信息 书名:《聪明的投资者》&…...
TypeScript声明文件
TypeScript声明文件 在JavaScript的生态系统中,随着项目的复杂度和规模不断增加,开发者对于类型安全和代码质量的追求也日益增长。TypeScript,作为JavaScript的一个超集,通过添加静态类型检查和ES6等新特性支持,极大地…...
.NET_WPF_使用Livecharts数据绑定图表
相关概念 LiveCharts 是一个开源的图表库,适用于多种 .NET 平台,包括 WPF、UWP、WinForms 等。LiveCharts 通过数据绑定与 MVVM 模式兼容,使得视图模型可以直接控制图表的显示,无需直接操作 UI 元素。这使得代码更加模块化&#x…...
一句JS代码,实现随机颜色的生成
今天我们只用 一句JS代码,实现随机颜色的生成,首先看一下效果: 每次刷新浏览器背景颜色都不一样 实现此效果的JS函数 : let randomColor () > ...: 定义一个箭头函数randomColor,用于生成一个随机颜色。 Math.ra…...
校园抢课助手【7】-抢课接口限流
在上一节中,该接口已经接受过风控的处理,过滤掉了机器人脚本请求,剩下都是人为的下单请求。为了防止用户短时间内高频率点击抢课链接,海量请求造成服务器过载,这里使用接口限流算法。 先介绍下几种常用的接口限流策略…...
char类型和int类型
一、char类型 在Java中,char(字符)类型用于表示单个字符,它是基本数据类型之一。以下是关于Java中char类型的一些重要信息: 表示方式: char类型用于存储Unicode字符,占用16位(即2个字…...
C++参悟:stl中的比较最大最小操作
stl中的比较最大最小操作 一、概述二、最小值1. min2. min_element 三、最大值1. max2. max_element 四、混合1. minmax2. minmax_element 一、概述 记录这里C11中常用的最小值和最大值的比较函数,最好的参考资料其实就是 https://zh.cppreference.com 最重要的查…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
深度学习水论文:mamba+图像增强
🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...
