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

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;
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 论文研读:ViT-V-Net—用于无监督3D医学图像配准的Vision Transformer
  • 《C++并发编程实战》笔记(一、二)
  • 抗量子密码算法:保障未来信息安全的新盾牌
  • 比赛获奖的武林秘籍:06 5 分钟速通比赛路演答辩,国奖选手的血泪经验!
  • 《JavaScript权威指南第7版》中文PDF+英文PDF+源代码 +JavaScript权威指南(第6版)(附源码)PDF下载阅读分享推荐
  • Hadoop-25 Sqoop迁移 增量数据导入 CDC 变化数据捕获 差量同步数据 触发器 快照 日志
  • 手机和电脑通过TCP传输
  • Boost搜索引擎
  • 构建Memcached帝国:分布式部署策略与实践指南
  • uni-app 保存号码到通讯录
  • Kithara与OpenCV (二)
  • 观察者模式的实现
  • 海外短剧开源系统UNIAPP源码(支持多语言/海外支付/快捷登录)
  • 【Docker 系列】学习路线
  • Xcode多任务处理指南:释放iOS应用的并发潜能
  • 实现windows 窗体的自己画,网上摘抄的,学习了
  • es6要点
  • Javascript编码规范
  • javascript数组去重/查找/插入/删除
  • KMP算法及优化
  • Laravel 实践之路: 数据库迁移与数据填充
  • LeetCode算法系列_0891_子序列宽度之和
  • Linux链接文件
  • MySQL的数据类型
  • vue--为什么data属性必须是一个函数
  • 纯 javascript 半自动式下滑一定高度,导航栏固定
  • 简单基于spring的redis配置(单机和集群模式)
  • 前端路由实现-history
  • 前端每日实战:70# 视频演示如何用纯 CSS 创作一只徘徊的果冻怪兽
  • 前端面试题总结
  • 实现简单的正则表达式引擎
  • 宾利慕尚创始人典藏版国内首秀,2025年前实现全系车型电动化 | 2019上海车展 ...
  • ​ssh免密码登录设置及问题总结
  • # 详解 JS 中的事件循环、宏/微任务、Primise对象、定时器函数,以及其在工作中的应用和注意事项
  • #我与Java虚拟机的故事#连载14:挑战高薪面试必看
  • $.each()与$(selector).each()
  • $.extend({},旧的,新的);合并对象,后面的覆盖前面的
  • (52)只出现一次的数字III
  • (vue)el-checkbox 实现展示区分 label 和 value(展示值与选中获取值需不同)
  • (待修改)PyG安装步骤
  • (二)c52学习之旅-简单了解单片机
  • (全部习题答案)研究生英语读写教程基础级教师用书PDF|| 研究生英语读写教程提高级教师用书PDF
  • (一)springboot2.7.6集成activit5.23.0之集成引擎
  • (转)fock函数详解
  • (转载)(官方)UE4--图像编程----着色器开发
  • ****Linux下Mysql的安装和配置
  • .NET 8.0 中有哪些新的变化?
  • .NET Core 版本不支持的问题
  • .NET 材料检测系统崩溃分析
  • .NET 的静态构造函数是否线程安全?答案是肯定的!
  • .NET 给NuGet包添加Readme
  • .net流程开发平台的一些难点(1)
  • /usr/bin/perl:bad interpreter:No such file or directory 的解决办法
  • @EnableAsync和@Async开始异步任务支持
  • [Android]如何调试Native memory crash issue