C/C++ 进阶(7)模拟实现map/set

个人主页:仍有未知等待探索-CSDN博客

专题分栏:C++

一、简介

map和set都是关联性容器,底层都是用红黑树写的。

特点:存的Key值都是唯一的,不重复。

map存的是键值对(Key—Value)。

set存的是键值(Key)。

二、map/set的模拟实现

map.h

#pragma once#include <iostream>
#include "RBTree.h"
using namespace std;template<class Key, class Value>
class map
{struct MapKeyOfT{const Key& operator()(const pair<Key, Value>& e){return e.first;}};public:typedef pair<Key, Value> PKV;typedef _RBTree_iterator<PKV, PKV*, PKV&> iterator;iterator begin(){return _t.begin();}iterator end(){return _t.end();}bool insert(const pair<Key, Value>& e){return _t.insert(e);}void inorder(){_t.inorder();}
private:RBTree<Key, pair<Key, Value>, MapKeyOfT> _t;
};

set.h

#pragma once#include "RBTree.h"template<class Key>
class set
{struct SetKeyOfT{const Key& operator()(const Key& e){return e;}};
public :typedef _RBTree_iterator<Key, Key*, Key&> iterator;iterator begin(){return _t.begin();}iterator end(){return _t.end();}bool insert(const Key& e){return _t.insert(e);}void inorder(){_t.inorder();}
private:RBTree<Key, Key, SetKeyOfT> _t;
};

RBTree.h

#pragma once#include<iostream>
using namespace std;enum color
{Red,Black
};
template <class ValueTpye>
struct RBTreeNode
{RBTreeNode(const ValueTpye& e = ValueTpye()):_left(nullptr),_right(nullptr),_parent(nullptr),_col(Red),_val(e){}struct RBTreeNode<ValueTpye>* _left;struct RBTreeNode<ValueTpye>* _right;struct RBTreeNode<ValueTpye>* _parent;int _col;ValueTpye _val;
};template<class ValueType, class Ptr, class Ref>
class _RBTree_iterator
{typedef RBTreeNode<ValueType> node;typedef _RBTree_iterator<ValueType, Ptr, Ref> iterator;
public:_RBTree_iterator(node* e):_node(e){}Ptr operator->(){return &_node->_val;}Ref operator*(){return _node->_val;}bool operator!=(iterator it){return _node != it._node;}iterator& operator++(){if (_node->_right){node* left = _node->_right;while (left->_left){left = left->_left;}_node = left;}else{node* cur = _node;node* p = cur->_parent;while (p && cur == p->_right){cur = p;p = p->_parent;}_node = p;}return *this;}
private:node* _node;
};template <class Key, class ValueType, class KeyOfT>
class RBTree
{
public:typedef RBTreeNode<ValueType> node;typedef _RBTree_iterator<ValueType, ValueType*, ValueType&> iterator;KeyOfT kot;RBTree():_root(nullptr){}iterator begin(){node* cur = _root;while (cur && cur->_left){cur = cur->_left;}return iterator(cur);}iterator end(){return iterator(nullptr);}node* find(const Key& e){node* cur = _root;while (cur){if (kot(cur->_val).first > e){cur = cur->_left;}else if (kot(cur->_val).first < e){cur = cur->_right;}else{return cur;}}return nullptr;}bool insert(const ValueType& e){// 根据二叉搜索树插入的方式进行插入node* cur = _root;node* parent = cur;while (cur){parent = cur;if (kot(cur->_val) > kot(e)){cur = cur->_left;}else if (kot(cur->_val) < kot(e)){cur = cur->_right;}else{return false;}}cur = new node(e);if (parent == nullptr){_root = cur;}else{if (kot(parent->_val) > kot(cur->_val)){parent->_left = cur;}else{parent->_right = cur;}cur->_parent = parent;}// 更新,对于不同的情况,进行不同的调整// parent 为黑、不存在,结束node* p = parent;while (p && p->_col == Red){node* g = p->_parent;if (g->_left == p){node* u = g->_right;// 叔叔存在且为红if (u && u->_col == Red){p->_col = u->_col = Black;g->_col = Red;// 继续往上处理cur = g;p = cur->_parent;}// 叔叔不存在且为黑else {//    g//  p   u// cif (cur == p->_left){// 右单旋RotateR(g);// 变色g->_col = Red;p->_col = Black;}//    g//  p   u//    celse {// 左右双旋RotateL(p);RotateR(g);// 变色cur->_col = Black;g->_col = Red;}// 叔叔不存在或者存在且为黑调整完,就不需要继续进行调整了break;}}else{node* u = g->_left;if (u && u->_col == Red){p->_col = u->_col = Black;g->_col = Red;// 继续往上处理cur = g;p = cur->_parent;}else {//    g//  u   p//        cif (cur == p->_right){// 左单旋RotateL(g);// 变色g->_col = Red;p->_col = Black;}//    g//  u   p//    celse {// 左右双旋RotateR(p);RotateL(g);// 变色cur->_col = Black;g->_col = Red;}// 叔叔不存在或者存在且为黑调整完,就不需要继续进行调整了break;}}}_root->_col = Black;return true;}void inorder(){_inorder(_root);}
private:void _inorder(node* root){if (root == nullptr) return;_inorder(root->_left);cout << kot(root->_val) << " ";_inorder(root->_right);}void RotateR(node* parent){node* subl = parent->_left;node* sublr = subl->_right;node* grandfather = parent->_parent;parent->_left = sublr;if (sublr){sublr->_parent = parent;}subl->_right = parent;parent->_parent = subl;subl ->_parent = grandfather;if (_root == parent){if (grandfather->_left == parent){grandfather->_left = subl;}else{grandfather->_right = subl;}}else{_root = subl;}}void RotateL(node* parent){node* subr = parent->_right;node* subrl = subr->_left;node* grandfather = parent->_parent;parent->_right = subrl;if (subrl){subrl->_parent = parent;}subr->_left = parent;parent->_parent = subr;subr ->_parent = grandfather;if (_root != parent){if (grandfather->_left == parent){grandfather->_left = subr;}else{grandfather->_right = subr;}}else{_root = subr;}}private:node* _root;
};

main.cpp(测试)

#define _CRT_SECURE_NO_WARNINGS 1#include "map.h"
#include "set.h"
//#include <map>
//#include <set>
#include <iostream>
using namespace std;void test1()
{int a[] = {5, 3, 7, 3, 7, 8, 4, 2, 9, 10};map<int, int> m;for (int e : a){m.insert(make_pair(e, e));}m.inorder();
}void test2()
{int a[] = {5, 3, 7, 3, 7, 8, 4, 2, 9, 10};set<int> s;for (int e : a){s.insert(e);}s.inorder();
}void test3()
{int a[] = {5, 3, 7, 3, 7, 8, 4, 2, 9, 10};set<int> s;for (int e : a){s.insert(e);}auto it = s.begin();while (it != s.end()){cout << *it << endl;++ it;}
}void test4()
{pair<int, int> a[] = {{5, 5}, {3, 3}, {7, 7}, {3, 3}, {7, 7}, {8, 8}, {4, 4}, {2, 2}, {9, 9}, {10, 10}};set<pair<int, int>> s;for (auto e : a){s.insert(e);}auto it = s.begin();while (it != s.end()){cout << (*it).first << " " << (*it).second << endl;++ it;}
}
int main()
{test1();return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Git的命令使用与IDEA内置git图形化的使用

Git 简介 Git 是分布式版本控制系统&#xff0c;它可以帮助开发人员跟踪和管理代码的更改。Git 可以记录代码的历史记录&#xff0c;并允许您在不同版本之间切换。 通过历史记录可以查看&#xff1a; 进行了哪些更改&#xff1f;谁进行了更改&#xff1f;何时进行了更改&#…

网络安全高级工具软件100套

1、 Nessus&#xff1a;最好的UNIX漏洞扫描工具 Nessus 是最好的免费网络漏洞扫描器&#xff0c;它可以运行于几乎所有的UNIX平台之上。它不止永久升级&#xff0c;还免费提供多达11000种插件&#xff08;但需要注册并接受EULA-acceptance–终端用户授权协议&#xff09;。 它…

在生产环境中部署Elasticsearch:最佳实践和故障排除技巧——聚合与搜索(三)

#在生产环境中部署Elasticsearch&#xff1a;最佳实践和故障排除技巧——聚合与搜索&#xff08;三&#xff09; 前言 文章目录 前言- 聚合和分析- 执行聚合操作- 1. 使用Java API执行聚合操作- 2. 使用CURL命令执行聚合操作- 1. 使用Java API执行度量操作- 2. 使用CURL命令执…

谷粒商城实战笔记-34-前端基础-ES6-promise异步编排

文章目录 一&#xff0c;回调地狱&#xff08;Callback Hell&#xff09;二&#xff0c;实战Promise1&#xff0c;场景说明2&#xff0c;回调地狱-传统实现3&#xff0c;使用Promise重构3.1 用Promise实现上述需求3.2 进一步重构 在ES6中&#xff0c;Promise是一个用于异步编程…

网络安全-内网安全加固方案

内网接入限制(MAC地址白名单) 只允许信任设备接入内网&#xff0c;且每次自动获取的IP地址不变(后续就可根据IP地址控制访问权限) 开启DHCP服务根据MAC地址静态分配固定IP地址 只允许可信的DHCP服务器分配IP地址(防止私建DHCP服务器) DHCP Snooping 信…

在Vue中,子组件向父组件传递数据

在Vue中&#xff0c;子组件向父组件传递数据通常通过两种方式实现&#xff1a;事件和回调函数。这两种方式允许子组件与其父组件进行通信&#xff0c;传递数据或触发特定的行为。 1. 通过事件传递数据 子组件可以通过触发自定义事件&#xff0c;并将数据作为事件的参数来向父组…

电脑案件冲突问题

一.故障展示 有一天我打开了电脑,发现3这个数字按键一直在输入,拔了外界的键盘,他这个按键还是会冲突 ,就如同上面的图一样 ,可能是电脑内部的键位进了灰卡住了什么东西导致的,于是我果断就电脑上的按键给扣下来了,扣的时候不知道里面的结构非常的谨慎,所以没导致里面的结构被损…

C#开发:Git的安装和使用

一、安装git 二、如何克隆代码&#xff1f; 1.找到某个本地目录&#xff0c;右键-gitbash 2. 输入以下代码&#xff08;红色是地址&#xff0c;在gitlab获取或联系管理员获取&#xff0c;下图为复制地址&#xff09;&#xff1a; git clone http://xxxxxxxxx.git 输入帐号和令…

【公益案例展】中国电信安全大模型——锻造安全行业能量转化的高性能引擎...

‍ 电信安全公益案例 本项目案例由电信安全投递并参与数据猿与上海大数据联盟联合推出的 #榜样的力量# 《2024中国数智产业最具社会责任感企业》榜单/奖项评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 以GPT系列为代表的大模型技术&#xff0c;展现了人工智能技术与应…

深度学习中的FLOPs补充

学习了博主的介绍&#xff08;深度学习中的FLOPs介绍及计算(注意区分FLOPS)-CSDN博客&#xff09;后&#xff0c;对我不理解的内容做了一点补充。 链接放到下边啦 https://blog.csdn.net/qq_41834400/article/details/120283103 FLOPs&#xff1a;注意s小写&#xff0c;是floa…

.Net Core 微服务之Consul(二)-集群搭建

引言: 集合上一期.Net Core 微服务之Consul(一)(.Net Core 微服务之Consul(一)-CSDN博客) 。 目录 一、 Consul集群搭建 1. 高可用 1.1 高可用性概念 1.2 高可用集群的基本原理 1.3 高可用集群的架构设计 1.3.1 主从复制架构 1.3.2 共享存储架构 1.3.3 负载均衡…

小程序字体图标使用iconfont 阿里巴巴矢量图

打开链接 iconfont官网进入 素材库-官方图标库中 挑选 适合的 字体图标 放到购物车点击 导航栏 中 购物车 图标把选中的 图标 添加至项目 然后在我的项目中 找到 项目 点击 【查看在线链接】 点击 图中 【暂无代码&#xff0c;点此生成】 生成 css 文件链接点击 css 打开 css 文…

OBD诊断(ISO15031) 06服务

文章目录 功能简介ISO 9141-2、ISO 14230-4和SAE J1850的诊断服务定义1、请求特定监控系统的车载监控测试结果请求消息定义&#xff08;读取支持的TID&#xff09;2、请求特定监控系统响应消息定义的车载监控测试结果&#xff08;报告支持的TID&#xff09;3、请求特定监控系统…

每天一个数据分析题(四百二十七)- 方差分析

下面是一个方差分析表&#xff1a; 表中A&#xff0c;B&#xff0c;C&#xff0c;D&#xff0c;E五个单元格内的数据分别是&#xff08; &#xff09;。 A. 40&#xff0c;5&#xff0c;35&#xff0c;60&#xff0c;1.71 B. 40&#xff0c;5&#xff0c;35&#xff0c;60&a…

The Web3 社区 Web3 产品经理课程

概述 / 深耕区块链行业 11 年&#xff0c;和很多产品经理都打过交道&#xff1b;遇到过优秀的产品经理&#xff0c;也遇到过比较拉垮的产品经理。多年工作中&#xff0c;曾在某些团队&#xff0c;承载技术兼产品经理的角色&#xff1b;也参与过很多 Web3 外包项目&#xff0c;包…

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第一篇 嵌入式Linux入门篇-第二十九章 NFS服务器的搭建和使用

i.MX8MM处理器采用了先进的14LPCFinFET工艺&#xff0c;提供更快的速度和更高的电源效率;四核Cortex-A53&#xff0c;单核Cortex-M4&#xff0c;多达五个内核 &#xff0c;主频高达1.8GHz&#xff0c;2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…

GEO的表达矩阵的探针ID转换成基因名称教程

GEO的表达矩阵的探针ID转换成基因名称教程 前情回顾 根据GSE id自动下载处理GEO数据(必须要运行的模块) 该模块的运行窗口截图 该模块的教程 知乎地址&#xff1a;根据GEO的GSE数据集编号自动下载和处理GEO数据教程: https://zhuanlan.zhihu.com/p/708053447 该根据GSE id…

大模型最新黑书:基于GPT-3、ChatGPT、GPT-4等Transformer架构的自然语言处理 PDF

今天给大家推荐一本丹尼斯罗斯曼(Denis Rothman)编写的关于大语言模型&#xff08;LLM&#xff09;权威教程<<大模型应用解决方案> 基于GPT-3、ChatGPT、GPT-4等Transformer架构的自然语言处理>&#xff01;Google工程总监Antonio Gulli作序&#xff0c;这含金量不…

观察者模式的实现

引言&#xff1a;观察者模式——程序中的“通信兵” 在现代战争中&#xff0c;通信是胜利的关键。信息力以网络、数据、算法、算力等为底层支撑&#xff0c;在现代战争中不断推动感知、决策、指控等各环节产生量变与质变。在软件架构中&#xff0c;观察者模式扮演着类似的角色…

最小二乘算法的解

最小二乘法&#xff08;Least Squares&#xff09;是一种用于寻找线性回归模型的最佳拟合直线的标准方法。它通过最小化数据点与拟合直线之间的平方差来找到最佳拟合的线性模型。 线性回归模型 假设我们有一组数据点 (xi,yi)&#xff0c;线性回归模型的目标是找到系数 w 和截…