map和set的底层实现

前言

map和set的底层都是由红黑树构成,但是map是kv模型,set是k模型。如何用一颗子树来同时封装map和set,还有怎么实现map/set的迭代器是这节重点

map和set的模板参数

struct MapKeyOfT{const K& operator()(const pair<K, V>& kv){return kv.first;}};
private:RBTree<K, pair<K, V>, MapKeyOfT> _t;
struct SetKeyOfT{const K& operator()(const K& k){return k;}};
private:RBTree<K, K, SetKeyOfT> _t;
template<class K, class T, class KeyOfT>

我们通过在红黑树模板中增加一个KeyOfT参数,通过map和set的模板来识别是

map还是set

这样后面的数据就要通过KeyOfT形成的对象来比较大小了

如·:查找函数

//查找函数
iterator Find(const K& key)
{KeyOfT kot;Node* cur = _root;while (cur){if (key < kot(cur->_data)) //key值小于该结点的值{cur = cur->_left; //在该结点的左子树当中查找}else if (key > kot(cur->_data)) //key值大于该结点的值{cur = cur->_right; //在该结点的右子树当中查找}else //找到了目标结点{return iterator(cur); //返回该结点}}return end(); //查找失败
}

迭代器

struct  _TreeIterator
{typedef RBTreeNode<T> Node;typedef _TreeIterator<T,Ptr,Ref> Self;typedef _TreeIterator<T, T*, T&> iterator;
};
//构造函数
__TreeIterator(Node* node):_node(node) //根据所给结点指针构造一个正向迭代器
{}

++运算符重载

1,右子树不为空,访问右子树的最左节点

2,右子树为空,找到该节点父亲,向上更新

Self& operator++(){if (_node->_right){Node* min = _node;while (min){min = min->_left;}_node = min;}else{Node* cur = _node;Node* parent = cur->_parent;while (parent && parent->_right == cur){cur = cur->_parent;parent = parent->_parent;}_node = parent;}return *this;}

--运算符重载

 Self& operator--(){if (_node->_left){Node* max = _node->_left;while (max->_right){max=max->_right}_node = max;}else{Node* cur = _node;Node* parent = cur->_parent;if (parent&&cur == parent->_left){cur = parent;parent = parent->_parent;}_node = parent;}return *this;}

迭代器总代码

template<class T,class Ref,class Ptr>
struct RBTreeIterator
{typedef RBTreeNode<T> Node;typedef RBTreeIterator<T,Ref, Ptr> Self;Node* _node;RBTreeIterator(Node* node):_node(node){}Ref operator*(){return _node->_data;}Ptr operator->(){return &_node->_data;}Self& operator++(){if (_node->_right){Node* min = _node;while (min){min = min->_left;}_node = min;}else{Node* cur = _node;Node* parent = cur->_parent;while (parent && parent->_right == cur){cur = cur->_parent;parent = parent->_parent;}_node = parent;}return *this;}bool operator!=(const Self& s) {return _node != s._node;}bool operator==(const Self& s) const{return _node == s._node;}Self& operator--(){if (_node->_left){Node* max = _node->_left;while (max->_right){max=max->_right}_node = max;}else{Node* cur = _node;Node* parent = cur->_parent;if (parent&&cur == parent->_left){cur = parent;parent = parent->_parent;}_node = parent;}return *this;}
};

RBTree代码实现(重点更改部分)

begin()和end()

  typedef RBTreeIterator<T, T&, T*> iterator;iterator begin(){Node* min = _root;while (min&&min->_left){min = min->_left;}return iterator(min);}iterator end(){return iterator(nullptr);}

构造函数/析构函数

RBTree():_root(nullptr){}~RBTree(){Destory(root);_root = nullptr;}void Destory(Node* root){if (root == nullptr){return;}Destory(root->_left);Destory(root->_right);delete root;}

析构函数是递归进行删除的

拷贝构造/赋值重载

    RBTree<K, T, KeyOfT>& operator=(RBTree<K, T, KeyOfT> t){swap(_root, t._root);return *this;}RBTRee(const RBTree<K, T, KeyOfT>& t){_root = Copy(t._root);}void* Copy(Node* root){if (root == nullptr){return nullptr;}Node* newroot = new Node(*root);newroot->_col = root->_col;newroot->_left = Copy(root->_left);newroot->_right = Copy(root->_right);if (newroot->_left){newroot->_left->_parent = newroot;}if (newroot->_right){newroot->_right->_parent = newroot;}return newroot; }

赋值重载利用现代写法

拷贝构造是递归进行拷贝的,由于只拷贝了节点,所以还要自己手动去链接父节点

插入函数的修改

插入函数修改成

  pair<iterator,bool> Insert(const T& data)

返回值为

 return make_pair(iterator(newnode), true);

、因为map中【】的本质就是调用insert函数,而【】在map中有多种功能:1:如果存在,返回value值2:如果不存在,则插入新节点

map/set都返回pair结构,其中map返回pair中的k值,set返回k值

set类

#pragma once#include"RBTree.h"namespace muyu
{template<class K>class set{struct SetofT{const K& operator()(const K& data){return data;}};public:typedef typename RBTree<K, K, SetofT>::const_iterator iterator;typedef typename RBTree<K, K, SetofT>::const_iterator const_iterator;public:pair<iterator, bool>& insert(const K& data){pair<RBTree<K, K, SetofT>::iterator, bool> tem = _t.Insert(data);pair<iterator, bool> res = tem;return res;}iterator begin()const{return _t.begin();}iterator end()const{return _t.end();}iterator find(const K& key){return _t.find(key);}private:RBTree<K, K, SetofT> _t;};
}

map类

#pragma once#include"RBTree.h"namespace muyu
{template<class K, class V>class map{struct MapofT{const K& operator()(const pair<K, V>& data){return data.first;}};public:typedef typename RBTree<K, pair<const K, V>, MapofT>::iterator iterator;typedef typename RBTree<K, pair<const K, V>, MapofT>::const_iterator const_iterator;public:pair<iterator, bool> insert(const pair<K, V>& data){return _t.Insert(data);}iterator begin(){return _t.begin();}iterator end(){return _t.end();}const_iterator begin()const{return _t.begin();}iterator find(const K& key){return _t.find(key);}const_iterator end()const{return _t.end();}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>, MapofT> _t;};
}

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

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

相关文章

XF 533-2012 挡烟垂壁

挡烟垂壁是指用不燃材料制成&#xff0c;垂直安装在建筑顶棚、横梁或吊顶下&#xff0c;能在火灾时形成一定的蓄烟空间的挡烟分隔设施。 XF 533-2012 挡烟垂壁测试项目 测试要求 测试标准 外观 XF 533 材料 XF 533 尺寸与极限偏差 XF 533 漏烟量 XF 533 耐高温性能 …

Zuul介绍

Zuul 是 Netflix 开源的一个云平台网络层代理&#xff0c;它主要用于路由、负载均衡、中间件通信和动态路由。Zuul 本质上是一个基于 JVM 的网关&#xff0c;它提供了以下功能&#xff1a; 1.路由&#xff1a;Zuul 允许客户端和服务器之间的所有入站和出站请求通过一个中心化的…

gbase8s数据库中根据系统表查看锁的现状和锁资源的监控(包括了两个onstat -g的关键命令和锁的查看演示)

1. 锁资源信息的查找和监控 1.1. 系统表中关于锁的信息 1.1.1. 当前正在占用锁资源和等待锁资源信息的系统表syslocks和测试 > select * from sysmaster:syslocks; dbsname test --数据库名称 tabname test --锁发生的表名称 rowidlk 6918 --发生锁的行号 keynum …

小红书怎么保存无水印图?

使用小红书APP长按保存的图片代有水印&#xff0c;很多人想知道保存小红书无水印图片的方法。本文教你如何保存到无水印的小红书图片&#xff0c;但是请注意不要侵犯作者图片的版权。 小红书怎么保存无水印图&#xff1f; 1、手机上打开小红书APP&#xff1b; 2、打开后&#…

昇思25天学习打卡营第13天|BERT

一、简介&#xff1a; BERT全称是来自变换器的双向编码器表征量&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;&#xff0c;它是Google于2018年末开发并发布的一种新型语言模型。与BERT模型相似的预训练语言模型例如问答、命名实体识别、自…

2.3章节Python中的数值类型

1.整型数值 2.浮点型数值 3.复数   Python中的数值类型清晰且丰富&#xff0c;主要分为以下几种类型&#xff0c;每种类型都有其特定的用途和特性。 一、整型数值 1.定义&#xff1a;整数类型用于表示整数值&#xff0c;如1、-5、100等。 2.特点&#xff1a; Python 3中的…

Quartz表达式:定时任务调度的高级配置与应用

Quartz表达式&#xff1a;定时任务调度的高级配置与应用 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 1. Quartz表达式概述 Quartz是一个强大的开源作业调…

卡尔曼滤波公式推导笔记

视频见B站上DR_CAN的卡尔曼滤波器 【卡尔曼滤波器】3_卡尔曼增益超详细数学推导 &#xff5e;全网最完整_哔哩哔哩_bilibili

动手学深度学习5.6 GPU-笔记练习(PyTorch)

以下内容为结合李沐老师的课程和教材补充的学习笔记&#xff0c;以及对课后练习的一些思考&#xff0c;自留回顾&#xff0c;也供同学之人交流参考。 本节课程地址&#xff1a;17 使用和购买 GPU【动手学深度学习v2】_哔哩哔哩_bilibili 本节教材地址&#xff1a;5.6. GPU —…

数据库定义语言(DDL)

数据库定义语言&#xff08;DDL&#xff09; 一、数据库操作 1、 查询所有的数据库 SHOW DATABASES;效果截图&#xff1a; 2、使用指定的数据库 use 2403 2403javaee;效果截图&#xff1a; 3、创建数据库 CREATE DATABASE 2404javaee;效果截图&#xff1a; 4、删除数据…

玩转springboot之springboot热部署

springboot热部署 热部署是在服务器运行时重新部署项目&#xff0c;直接加载整个应用&#xff0c;会释放内存&#xff0c;不过比较耗时 配置tomcat实现热部署 有三种方式 方式一 把项目web文件放在webapps目录下 方式二 在tomcat\conf\server.xml中的<host>标签内添加<…

面向阿克曼移动机器人(自行车模型)的LQR(最优二次型调节器)路径跟踪方法

线性二次调节器&#xff08;Linear Quadratic Regulator&#xff0c;LQR&#xff09;是针对线性系统的最优控制方法。LQR 方法标准的求解体系是在考虑到损耗尽可能小的情况下, 以尽量小的代价平衡其他状态分量。一般情况下&#xff0c;线性系统在LQR 控制方法中用状态空间方程描…

opencv c++ python获取摄像头默认分辨率及设置缩放倍数

c代码 #include <opencv2/opencv.hpp> #include <iostream>int main() {// 创建一个VideoCapture对象cv::VideoCapture cap(0); // 参数0表示打开默认摄像头// 检查摄像头是否成功打开if (!cap.isOpened()) {std::cerr << "Error: Could not open came…

Android super.img结构及解包和重新组包

Android super.img结构及解包和重新组包 从Android10版本开始&#xff0c;Android系统使用动态分区&#xff0c;system、vendor、 odm等都包含在super.img里面&#xff0c;编译后的最终镜像不再有这些单独的 image&#xff0c;取而代之的是一个总的 super.img. 1. 基础知识 …

【Unity】RPG2D龙城纷争(七)关卡编辑器之剧情编辑

更新日期:2024年7月1日。 项目源码:第五章发布(正式开始游戏逻辑的章节) 索引 简介一、剧情编辑1.对话数据集2.对话触发方式3.选择对话角色4.设置对话到关卡5.通关条件简介 严格来说,剧情编辑不在关卡编辑器界面中完成,只不过它仍然属于关卡编辑的范畴。 在我们的设想中…

鸿蒙:页面动画-属性动画、显示动画

1.属性动画是通过设置组件的animation属性来给组件添加动画&#xff0c;当组件的width、height、backgroundColor、scale等属性变更时可以实现过渡渐变效果。 2.显示动画是通过全局animateTo函数来修改组件的属性&#xff0c;实现属性变化时的渐变过渡效果。 核心属性

【你也能从零基础学会网站开发】关系型数据库中的表(Table)设计结构以及核心组成部分

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;程序猿、设计师、技术分享 &#x1f40b; 希望大家多多支持, 我们一起学习和进步&#xff01; &#x1f3c5; 欢迎评论 ❤️点赞&#x1f4ac;评论 &#x1f4c2;收藏 &#x1f4c2;加关注 关系型数据库中…

【Git 学习笔记】Ch1.1 Git 简介 + Ch1.2 Git 对象

还是绪个言吧 今天整理 GitHub 仓库&#xff0c;无意间翻到了几年前自学 Git 的笔记。要论知识的稳定性&#xff0c;Git 应该能挤进前三——只要仓库还在&#xff0c;理论上当时的所有开发细节都可以追溯出来。正好过段时间会用到 Git&#xff0c;现在整理出来就当温故知新了。…

DiffBIR: Towards Blind Image Restoration with Generative Diffusion Prior

深圳先进研究院&上海ai lab&港中文https://github.com/XPixelGroup/DiffBIRhttps://arxiv.org/pdf/2308.15070 问题引入 使用一个统一的框架来处理image restoration任务&#xff0c;包含图片超分BSR&#xff0c;图片去噪BID和人脸restoration BFR&#xff0c;分为两…

【从零开始学架构 架构基础】五 架构设计的复杂度来源:低成本、安全、规模

架构设计的复杂度来源其实就是架构设计要解决的问题&#xff0c;主要有如下几个&#xff1a;高性能、高可用、可扩展、低成本、安全、规模。复杂度的关键&#xff0c;就是新旧技术之间不是完全的替代关系&#xff0c;有交叉&#xff0c;有各自的特点&#xff0c;所以才需要具体…