C++语法——map与set的封装原理

news2024/11/26 0:25:30

目录

一.数据类型封装

(一).封装方式

(二).封装后如何取key比较

 二.迭代器封装

(一).底层迭代器(红黑树中)

①迭代器++

②迭代器-- 

(二).begin&end&const


一.数据类型封装

(一).封装方式

我们知道,map与set所使用的都是红黑树,但是map是key&value模型,set是key模型。

map需要传两个类型而set只用传一个类型,这在底层红黑树中该怎么兼容呢?

透过SGI版stl_tree.h我们可以看到,红黑树有两个模板参数分别表示key和value。重点来了:

对于map而言需要传入key和pair<key, value>分别给红黑树的key和value。

set需要传key和key给红黑树的key和value。

再看map与set源码(进行部分截取):

 如果自制的话,大致如此:

template<class K, class V>
class Map
{
	typedef rb_tree<K, pair<K, V>, MapOfV<K, pair<K, V>>> tree;
public:
	//...

private:
	tree _t;
};
template<class K>
class Set
{
	typedef rb_tree<K, K, SetOfV<K>> tree;
public:
	//...

private:
	tree _t;
};

(二).封装后如何取key比较

但是这种封装有一个问题,就是在底层红黑树中,是直接拿value进行比较,那这该怎么办呢?

仿函数取value中key值来解决。

对于map而言,传仿函数给红黑树,调用仿函数取value(实际是pair<key, value>)中的key值

对于set而言,key和value中的值实际上都是key,也传仿函数取即可。

因此,对于上述代码我们看到map和set分别传入了仿函数MapOfV和SetOfV。

仿函数均在上层中(map/set)实现,传入底层红黑树。

代码实现如下(简易):

template<class K, class V>
//传入分别是key和pair<key, value>
//typedef rb_tree<K, pair<K, V>, MapOfV<K, pair<K, V>>> tree;
class MapOfV
{
public:
	K operator()(V kv) const
	{
		return kv.first;
	}
};
template<class K>
//typedef rb_tree<K, K, SetOfV<K>> tree;
class SetOfV
{
public:
	K operator()(K k) const
	{
		return k;
	}
};

 二.迭代器封装

因为map和set底层都是红黑树,因此迭代器实现在红黑树中(底层),而map和set只是调用红黑树的迭代器

(一).底层迭代器(红黑树中)

因为红黑树也是由一个个节点组成,这就很容易想到list的迭代器。list迭代器是用类封装,迭代器内部定义一个指针指向节点,对迭代器的操作底层是对迭代器内部指针的操作。

红黑树的迭代器与之类似,也是使用一个类来表示迭代器,内部有一个指向树节点的指针。只要了解过list迭代器都能想出来,不了解可以看看这篇文章哦:为什么List的迭代器是类模板?

对于解引用*和箭头->的封装与list相同,直接转化成对节点指针的操作。

关键在于++和--。 

①迭代器++

红黑树也是二叉树,我们就直接以二叉树为例:


 这里要分两种情况: 

 第一种:节点有右子树,此时要向下走。

以1号节点为例,因为有右子树,++后就是6号节点?——错!

二叉树迭代是前序遍历的方式,++后应该是5号节点,即右子树的最左节点!

第二种:节点没有右子树,此时要向上走。

对比3号和5号节点,都是叶子节点,但是3号节点++后是1号节点,5号++后是6号节点。

得出结论:如果当前节点是父节点的左子树,那++后就是父节点如果是右子树,那么需要向上找直到当前节点是父节点左子树,此时父节点是++后节点。

如果是节点7那么++会一直判断到根节点4,因此,迭代器end()可以设置为root的父节点(null)。

原理很简单,如果是右子节点那说明对于父节点而言你就是++后会找到的节点,但是对于自己而言++后就不可能是父节点。

代码如下:

Self operator++()
{
	goBack();
	return *this;
}
void goBack()
{
	if (_node->right)//如果右子节点不为空
	{
		Node* right = _node->right;
		while (right->left)//直到找到右子树最左节点
		{
			right = right->left;
		}
		_node = right;
	}
	else//右子树为空
	{
		Node* parent = _node->parent, * cur = _node;
		while (parent && cur == parent->right)//直到cur是parent的左子节点为止
		{
			cur = parent;
			parent = cur->parent;
		}
		_node = parent;
	}
}

②迭代器-- 

有了++的理解,--操作就简单了。

还是以该树为例:
 也要分两种情况:
第一种:有左子树,向下走。

以根节点4为例,--之后不是节点2而是节点3。对于有左子树的节点而言,--之后的节点是左子树的最右子节点。

第二种:没有左子树,向上走。

对比节点3和节点5,节点3--之后是节点2,节点5--之后是节点4。可以看出,如果节点是父节点的右子节点,那么--之后就是父节点。但如果是左子节点,那么需要向上判断直到是父节点的右子节点为止。或者如节点1一样,一直判断到根节点为止。

其原理就是如果是父节点的左子节点,那么说明父节点在自己之后,如果是右子节点那么说明在父节点之后。

代码如下:

Self operator--(int)
{
	Self it(_node);
	goHead();
	return it;
}
void goHead()
{
	if (_node->left)//有左子树
	{
		Node* right = _node->left;
		while (right->right)//直到左子树的最右子节点
		{
			right = right->right;
		}
		_node = right;
	}
	else//无左子树
	{
		Node* parent = _node->parent, * cur = _node;
		while (parent&& cur = parent->left)//直到cur是parent的右子节点
		{
			cur = parent;
			parent = cur->parent;
		}
		_node = parent;
	}
}

(二).begin&end&const

迭代器的begin和end只能在rb_tree中实现,对于begin而言,返回红黑树最左节点的迭代器,end返回root的父节点迭代器(空节点迭代器)。

对于const,首先我们应该知道不管map还是set均不支持对key的修改

但在实现上map和set大有不同

map采用在传入时就传入const key,而set采用将迭代器都使用底层const迭代器

用几个小时来制定计划,可以节省几周的编程时间—— 未名


如有错误,敬请斧正

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

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

相关文章

【Pandas数据处理100例】(七十三):Pandas使用groupBy()计算每个组的均值

前言 大家好,我是阿光。 本专栏整理了《Pandas数据分析处理》,内包含了各种常见的数据处理,以及Pandas内置函数的使用方法,帮助我们快速便捷的处理表格数据。 正在更新中~ ✨ 🚨 我的项目环境: 平台:Windows10语言环境:python3.7编译器:PyCharmPandas版本:1.3.5N…

【Python数据科学 | 11】应用实战:我的第一个开源项目-基金定投回测工具

这是机器未来的第60篇文章 原文首发地址&#xff1a;https://robotsfutures.blog.csdn.net/article/details/127712752 《Python数据科学快速入门系列》快速导航&#xff1a; 【Python数据科学快速入门系列 | 01】Numpy初窥——基础概念【Python数据科学快速入门系列 | 02】创…

kotlin入门学习文档

kotlin入门学习文档 前言&#xff1a;本文会着重对比java和kotlin&#xff0c;方便Java选手理解 提前总结&#xff1a;kotlin在服务端应用本质上是基于Java进行的改进&#xff0c;底层都是由JVM翻译成底层语言&#xff0c;我们只需要关注kotlin本身的代码&#xff0c;无需担心…

[附源码]Python计算机毕业设计Django的手机电商网站

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

lte基站学习总结

目录 1.nanocell基站的介 2.lte的网络结构 2.1 网络实体 2.2 功能划分 2.3功能描述 2.4业务类型 2.5语音回落原理 3 S1接口上用户注册消息的简介 3.1 S1接口的位置 3.2 S1接口的协议栈关系 3.3 S1接口建立实例 4 3g用户附着流程 5. Lte用户开机附着过程 1.nanocell基站…

[附源码]计算机毕业设计springboot农村人居环境治理监管系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

你安全吗?丨黑客掌握的翻垃圾技术有哪些?大家要警惕!

作者&#xff1a;黑蛋 黑客并不全是大家所想象中&#xff0c;一个黑面罩&#xff0c;一台电脑&#xff0c;绿花花的代码界面&#xff0c;噼里啪啦对着计算机一顿猛敲&#xff0c; image-20221114221628695 除了专业的计算机技术&#xff0c;黑客还有其他非技术手段。今天我们…

拆解小鹏汽车财报:连续三个季度收入下滑,门店月均销量仅为8辆

11月30日&#xff0c;小鹏汽车&#xff08;NYSE:XPEV、HK:09868&#xff09;公布了截至2022年9月30日的2022年第三季度财报。财报显示&#xff0c;小鹏汽车2022年第三季营收68.2亿元&#xff0c;略低于市场预期的68.8亿元&#xff0c;较2021年同期增长19.3%&#xff0c;环比下降…

【JVM故障问题排查心得】「内存诊断系列」JVM内存与Kubernetes中pod的内存、容器的内存不一致所引发的OOMKilled问题总结(下)

承接上文 之前文章根据《【JVM故障问题排查心得】「内存诊断系列」JVM内存与Kubernetes中pod的内存、容器的内存不一致所引发的OOMKilled问题总结&#xff08;上&#xff09;》我们知道了如何进行设置和控制对应的堆内存和容器内存的之间的关系&#xff0c;所以防止JVM的堆内存…

[附源码]计算机毕业设计springboot教学辅助系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

[附源码]Python计算机毕业设计Django的云网盘设计

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

12.Java 使用中间件优雅停机方案设计与实现

内核中的信号量开始聊起。 从内核层我们接着会聊到 JVM 层&#xff0c;在 JVM 层一探优雅停机底层的技术玄机。 随后我们会从 JVM 层一路奔袭到 Spring 然后到 Dubbo。在这个过程中&#xff0c;笔者还会带大家一起 Shooting Dubbo 在优雅停机下的一个 Bug&#xff0c;并为大家…

“数智芯生,云端共创”,利尔达精彩亮相第十八届国际物联网展

“数智芯生&#xff0c;云端共创”&#xff0c;11月15日&#xff0c;为期三天的IOTE 2022 第十八届国际物联网展在深圳国际会展中心&#xff08;宝安&#xff09;盛大开幕。来自全球的感知层、传输层以及应用层的400多家企业共聚一堂&#xff0c;分享发展成果&#xff0c;探讨物…

Android App Icon 替换

今天老板提出有一个需求, 说咱家App icon太丑, 老板说随便什么icon都行 1. 为了随便找一个icon, 我去google了一个图 2. ok, 随便找到一个icon, 下载下来保存文件叫做 jay_web_app.png, 长得还行 3. Android icon 替换开始, 首先找到原来icon的位置, 怎么找呢? 有一个简单直接…

每日一题·对原型和原型链的理解(12/1)

目录 1. 原型链为什么要出现&#xff1f; 2. 原型是什么 3. 原型链是什么 4. 一些代码片段 1. 原型链为什么要出现&#xff1f; 声明2个实例&#xff0c;每个实例都会独立创建sayHi方法&#xff0c;非常占用内存。一样的方法&#xff0c;可以放在原型对象上共用。 function…

[附源码]SSM计算机毕业设计疫情背景下社区公共卫生服务系统JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

[附源码]Python计算机毕业设计SSM辽宁省高考志愿智能辅助填报系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

中间件版本信息泄露:Microsoft-HTTPAPI/2.0

中间件版本信息泄露&#xff1a;Microsoft-HTTPAPI 修复漏洞现象风险描述修复建议漏洞现象 server版本信息泄露 风险描述 修改请求url会导致所使用服务或中间件版本泄露&#xff0c;从而为攻击者提供进一步攻击的机会 修复建议 如果DisableServerHeader不存在&#xff0c…

【数据结构】二叉树的实现

文章目录一、二叉树的概念二、特殊的二叉树三、二叉树的性质四、二叉树的存储结构五、二叉树链式结构实现&#xff08;1&#xff09;创建结构体&#xff08;2&#xff09;具体函数实现及实现1.0 二叉树的构建1.1 二叉树的销毁1.2 二叉树节点个数1.3 二叉树叶子结点个数1.4 二叉…

【Pandas数据处理100例】(九十):Pandas使用period_range()生成固定间隔日期

前言 大家好,我是阿光。 本专栏整理了《Pandas数据分析处理》,内包含了各种常见的数据处理,以及Pandas内置函数的使用方法,帮助我们快速便捷的处理表格数据。 正在更新中~ ✨ 🚨 我的项目环境: 平台:Windows10语言环境:python3.7编译器:PyCharmPandas版本:1.3.5N…