C++进阶:map与set简单自实现

目录

  • 1. map与set封装红黑树的方式
    • 1.1 大概实现思路
    • 1.2 红黑树模板抽象
    • 1.3 红黑树的迭代器
  • 2. 红黑树模板的实现
    • 2.1 结点结构的定义
    • 2.2 红黑树迭代器的实现
      • 2.2.1 迭代器的结构
      • 2.2.2 迭代器的方法实现
    • 2.3 树结构的定义
    • 2.4 红黑树接口实现
      • 2.4.1 插入
      • 2.4.2 查找
      • 2.4.3 迭代器相关
  • 3. map与set的自实现
    • 3.1 set封装
    • 3.2 map封装

1. map与set封装红黑树的方式

1.1 大概实现思路

  1. STL库中,实现的map与set其底层都为红黑树这种数据结构,在前面的学习中,我们已经简单模拟实现了红黑树。
  2. 因此,对于map与set的实现无需再去从零开始一一构建,而是可以采用类似于栈与队列这两个容器适配器的形式,直接将红黑树进行封装,调用其的各种方法接口间接实现。

1.2 红黑树模板抽象

  1. 虽然map与set的底层数据结构都为红黑树,但是,它们也并不是完全相同,map中存储的数据结点为KV类型,而set中存储的数据结点为K类型,所以,两者在接口与使用上也有所不同。
  2. 可仅仅因此不大的差别就再写一份高度类同的红黑树代码,就不免冗余性过高,由此,我们仿照库中实现的类似方式,将红黑树抽象为模板,通过模板参数来调整细节的方式,来同时适配map与set的需求。
//红黑树模板参数
template<class K, class T, class KeyOfT>
//参数K:set与map的key值类型,K参数的存在是必要的,否则无法进行此类型函数参数的声明
//参数T:set中也为key值类型,而map中为pair<K, V>类型
//参数KeyOfT:仿函数类型,从T类型结点中提取出key值,进行查找,插入等操作必须获知与比对key值

1.3 红黑树的迭代器

  1. 当调用库中的map与set容器时,我们使用相应迭代器遍历其中存储数据,得到的是一串排序好的有序数据。
  2. 因为map与set的底层本质上为一棵搜索二叉树,这种遍历后得到的数据特点,我们不难知道,迭代器底层实则是在由整颗树最左侧结点做中序遍历,那么,其底层的逻辑究竟应该怎么去实现呢?

2. 红黑树模板的实现

2.1 结点结构的定义

//结点结构
enum colour
{Red,Black
};template<class K, class T>
struct RBTreeNode
{RBTreeNode<K, T>* _left;RBTreeNode<K, T>* _right;RBTreeNode<K, T>* _parent;T _kv;colour _col;RBTreeNode(const T& kv):_left(nullptr),_right(nullptr),_parent(nullptr),_kv(kv),_col(Red){}
};

2.2 红黑树迭代器的实现

2.2.1 迭代器的结构

//定义一个迭代器模板,适配出普通迭代器与const迭代器
template<class K, class T, class Ref, class Ptr>
class RBTree_iterator
{typedef RBTreeNode<K, T> RBTNode;
public://构造RBTree_iterator(RBTNode* node):_node(node){}//拷贝构造RBTree_iterator(const RBTree_iterator& it){_node = it._node;}//后置++,左根右RBTree_iterator operator++(int);//后置--,右根左RBTree_iterator operator--(int);//const T&Ref operator*();//const T*Ptr operator->();//指向结点相同bool operator==(RBTree_iterator it);bool operator!=(RBTree_iterator it);private:RBTNode* _node;
};

2.2.2 迭代器的方法实现

  1. 杂项
//const T&
Ref operator*()
{return _node->_kv;
}//const T*
Ptr operator->()
{return &_node->_kv;
}//指向结点相同
bool operator==(RBTree_iterator it)
{return _node == it._node;
}bool operator!=(RBTree_iterator it)
{return _node != it._node;
}
  1. 后置++与–
    在这里插入图片描述
//先使用,再++
//operator++,左根右
RBTree_iterator operator++(int)
{RBTree_iterator cp(*this);//左根右if (_node->_right){//向左找RBTNode* SubLeft = _node->_right;while (SubLeft->_left){SubLeft = SubLeft->_left;}_node = SubLeft;}else{RBTNode* cur = _node;RBTNode* parent = cur->_parent;if (cur == parent->_left){_node = parent;}else{//一层一层向上找,空结点检测while (parent && cur == parent->_right){cur = parent;parent = cur->_parent;}_node = parent;}}return cp;
}//operator--,右根左
RBTreeNode_iterator operator--(int)
{RBTree_iterator cp(*this);//右根左if (_node->_left){//向右找RBTNode* SubRight = _node->_left;while (SubRight->_right){SubRight = SubRight->_right;}_node = SubRight;}else{RBTNode* cur = _node;RBTNode* parent = _node->_parent;while (parent && cur == parent->_left){cur = parent;parent = cur->_parent;}_node = parent;//处理逻辑同时符合两种情况}return cp;
}

2.3 树结构的定义

//树结构
template<class K, class T, class KeyOfT>
class RBTree
{typedef RBTreeNode<K, T> RBTNode;
public://查找bool Find(const K& key);//插入pair<iterator, bool> Insert(const T& kv);private:RBTNode* _root = nullptr;KeyOfT con;
}

2.4 红黑树接口实现

2.4.1 插入

//插入
pair<iterator, bool> Insert(const T& kv)
{//找到插入位置RBTNode* cur = _root;RBTNode* parent = nullptr;while (cur){if (con(kv) < con(cur->_kv)){parent = cur;cur = cur->_left;}else if (con(kv) > con(cur->_kv)){parent = cur;cur = cur->_right;}else{//有相同值,插入失败//return false;return make_pair(iterator(cur), false);}}//插入RBTNode* newnode = new RBTNode(kv);cur = newnode;if (_root == nullptr)//根结点{_root = cur;_root->_col = Black;//return true;return make_pair(iterator(cur), true);}else{if (con(kv) < con(parent->_kv)){parent->_left = cur;cur->_parent = parent;}else{parent->_right = cur;cur->_parent = parent;}}//判断与调整while (parent){//父亲结点为黑色if (parent->_col == Black){break;}else//父结点为红色{RBTNode* grandparent = parent->_parent;RBTNode* uncle = grandparent->_left;if (parent == grandparent->_left){uncle = grandparent->_right;}//叔叔结点存在且为红色if (uncle && uncle->_col == Red){parent->_col = uncle->_col = Black;grandparent->_col = Red;cur = grandparent;//注,父节点存放变量也需重置parent = cur->_parent;}else//叔叔结点为黑色/不存在{if (parent == grandparent->_left)//左外高{if (cur == parent->_left)//右单旋{//      g//   p      u//cRotateR(grandparent);parent->_col = Black;grandparent->_col = Red;}else//左右双旋{//      g//   p      u//     cRotateLR(grandparent);cur->_col = Black;grandparent->_col = Red;}}else//右外高{if (cur == parent->_right)//左单旋{//   g//u      p//          cRotateL(grandparent);parent->_col = Black;grandparent->_col = Red;}else//右左双旋{//   g//u      p//     cRotateRL(grandparent);cur->_col = Black;grandparent->_col = Red;}}break;}}}_root->_col = Black;return make_pair(iterator(newnode), true);
}

2.4.2 查找

//查找
bool Find(K key)
{RBTNode* cur = _root;while (cur){if (key < con(cur->_kv)){cur = cur->_left;}else if (key > con(cur->_kv)){cur = cur->_right;}else{return true;}}return false;
}

2.4.3 迭代器相关

typedef RBTree_iterator<K, T, T&, T*> iterator;
typedef RBTree_iterator<K, T, const T&, const T*> const_iterator;iterator begin()
{RBTNode* cur = _root;while (cur->_left){cur = cur->_left;}return cur;
}iterator end()
{return nullptr;
}const iterator cbegin() const
{RBTNode* cur = _root;while (cur->_left){cur = cur->_left;}return cur;
}const iterator cend() const
{return nullptr;
}

3. map与set的自实现

3.1 set封装

template<class K>
class myset
{struct KeyOfT{K operator()(const K& key){return key;}};typedef RBTree_iterator<K, K, K&, K*> iterator;typedef RBTree_iterator<K, K, const K&, const K*> const_iterator;
public:bool Find(K key){return tree.Find(key);}pair<iterator, bool> Insert(K key){return tree.Insert(key);}iterator begin(){return tree.begin();}iterator end(){return tree.end();}const_iterator cbegin() const{return tree.cbegin();}const_iterator cend() const{return tree.cend();}void InOrder(){tree.InOrder();}private:RBTree<K, K, KeyOfT> tree;
};

3.2 map封装

template<class K, class V>
class mymap
{struct KeyOfT{K operator()(const pair<const K, V> kv){return kv.first;}};typedef RBTree_iterator<K, pair<const K, V>, pair<const K, V>&, pair<const K, V>*> iterator;typedef RBTree_iterator<K, pair<const K, V>, const pair<const K, V>&, const pair<const K, V>*> const_iterator;
public:bool Find(K key){return tree.Find(key);}pair<iterator, bool> Insert(const pair<K, V> kv){return tree.Insert(kv);}//迭代器iterator begin(){return tree.begin();}iterator end(){return tree.end();}const_iterator cbegin() const{return tree.cbegin();}const_iterator cend() const{return tree.cend();}V& operator[](const K key){pair<iterator, bool> ret = Insert(make_pair(key, V()));return ret.first->second;}private:RBTree<K, pair<const K, V>, KeyOfT> tree;
};

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

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

相关文章

pytest + yaml 框架 - 参数化读取文件路径优化

针对小伙伴提出参数化时读取外部文件&#xff0c;在项目根路径运行没问题&#xff0c;但是进入到项目下子文件夹运行用例&#xff0c;就会找不到文件问题做了优化。 关于参数化读取外部文件相关内容参考前面这篇pytest yaml 框架 -25.参数化数据支持读取外部文件txt/csv/json/…

随手笔记-GNN(朴素图神经网络)

自己看代码随手写的一点备忘录&#xff0c;自己看的&#xff0c;不喜勿喷 GNN (《------ 代码) 刚开始我还在怀疑为什么没有加weigth bias&#xff0c;已经为什么权重才两个&#xff0c;原来是对node_feats进行的network的传播&#xff0c;而且自己内部直接进行了。 下面是一…

【api接口开通教程】YouTube Data API v3申请流程

一、背景调查 1.1 API接口介绍 采集youtube数据&#xff0c;大体分为两种方案&#xff1a;一种是基于爬虫&#xff0c;一种是基于API接口。 说人话就是&#xff1a;爬虫相当于走后门、爬窗户&#xff08;利用技术手段窃取&#xff0c;人家没说给&#xff0c;但我硬拿&#x…

ssrf漏洞学习——基础知识

一、SSRF是什么&#xff1f; SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。 一般情况下&#xff0c;SSRF攻击的目标是从外网无法访问的内部系统。&#xff08;正是因为它是由服务端发起的&#xff0c;所以它能…

leetcode每日一题第七十二天

class Solution { public:TreeNode* searchBST(TreeNode* root, int val) {if(!root) return root;if(root->val val) return root;else if(root->val > val) return searchBST(root->left,val);else return searchBST(root->right,val);} };

日志打印传值 传引用 右值引用性能测试(Linux/QNX)

结论 Linux平台和qnx平台优化后传值性能都是比传引用的差&#xff0c;也比传右值的差&#xff0c;因此传参时有必要传递引用。 测试代码 #include <cstdint> #include <ctime> #include <string>#ifdef __linux__#define ITERATIONS 10000000 #else#defin…

(七)JSP教程——session对象

浏览器和Web服务器之间的交互通过HTTP协议来完成&#xff0c;HTTP协议是一种无状态的协议&#xff0c;服务器端无法保留浏览器每次与服务器的连接信息&#xff0c;无法判断每次连接的是否为同一客户端。为了让服务器端记住客户端的连接信息&#xff0c;可以使用session对象来记…

STM32--4G DTU 及 阿里云

模块概述 ATK-IDM750C/IDM751C 是正点原子(ALIENTEK)团队开发的一款高性能 4G Cat1 DTU 产品&#xff0c; 支持移动 4G、联通 4G 和电信 4G 手机卡。它以高速率、低延迟和无线数传作为核心功能&#xff0c; 可快速解决应用场景下的无线数传方案。 它支持 TCP/UDP/HTTP/MQTT/DN…

kafka(七)——消息偏移(消费者)

概念 消费者消费完消息后&#xff0c;向_consumer_offset主题发送消息&#xff0c;用来保存每个分区的偏移量。 流程说明 consumer发送JoinGroup请求&#xff1b;coordinator选出一个consumer作为leader&#xff0c;并将topics发送给leader消费者&#xff1b;leader consumer…

全网最详细的Python自动化测试(unittest框架)

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

ssm105基于JAVAEE技术校园车辆管理系统+jsp

校园车辆管理系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本校园车辆管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短…

gtest的编译与使用

文章目录 gtest的编译与使用概述笔记CMake参数官方文档测试程序测试效果END gtest的编译与使用 概述 gTest是 googletest的缩写&#xff0c;如果直接找gTest项目&#xff0c;是找不到的。 库地址 https://github.com/google/googletest.git 迁出到本地后&#xff0c;切到最新…

景源畅信数字:抖音小店的入住门槛大不大?

近年来&#xff0c;随着短视频平台的崛起&#xff0c;抖音小店逐渐成为了众多商家和创业者关注的焦点。那么&#xff0c;抖音小店的入住门槛究竟大不大呢?本文将从四个方面对这一问题进行详细阐述。 一、注册流程 抖音小店的注册流程相对简单&#xff0c;只需按照官方指引完成…

HackBar 新手使用教程(入门)

啥是Hackbar&#xff1f; Hackbar是一个Firefox 的插件,它的功能类似于地址栏,但是它里面的数据不受服务器的相应触发的重定向等其它变化的影响。 有网址的载入于访问,联合查询,各种编码,数据加密功能。 这个Hackbar可以帮助你在测试SQL注入,XSS漏洞和网站的安全性,主要是帮助…

揭秘丨文字游侠AI工具:一键生成高质量爆文赚米,提升20倍写作效率,附上渠道和实操教程!

在这个信息泛滥的时代&#xff0c;内容创作者们不断寻求更高效、更创新的方法&#xff0c;以便在众多竞争者中脱颖而出。虽然平台如今日头条为他们提供了展示才华和获取收益的舞台&#xff0c;但如何在激烈的竞争中站稳脚跟&#xff0c;仍是他们需要面对的挑战。然而&#xff0…

​Inf-DiT:Upsampling Any-Resolution Image、Vidu、MVDiff、Trio-ViT

本文首发于公众号&#xff1a;机器感知 ​Inf-DiT&#xff1a;Upsampling Any-Resolution Image、Vidu、MVDiff、Trio-ViT Inf-DiT: Upsampling Any-Resolution Image with Memory-Efficient Diffusion Transformer Diffusion models have shown remarkable performance in im…

js原生手写一个拖拽小功能

先上效果图 附上代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" /><meta name"viewport" content"widthd…

Python自动化测试五大框架(测试员收藏夹必备)

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

Java 语法 (杂七杂八的知识)

面向对象三大特性 封装, 多态, 继承 基本数据类型 一字节 (Byte) 占八位 (bit) JDK, JRE, JVM JDK (Java Development Kit) : Java 开发工具包, 包括了 JRE, 编译器 javac, 和调试工具 Jconsole, jstack 等 JRE (Java Runtime Environment) : Java 运行时环境, 包括了 JVM , …

基于Vue3与ElementUI Plus的酷企秀场景可视化DIY设计器:前端技术引领下的数字化展示新篇章

一、引言 在当今信息化高速发展的时代&#xff0c;企业对于展示自身形象、提升用户体验以及增强品牌知名度的需求日益迫切。针对这一市场需求&#xff0c;我们推出了基于Vue3与ElementUI Plus的酷企秀场景可视化DIY设计器。该产品不仅具备电子画册、VR全景、地图秀三大核心功能…