c++编程(25)——unordered_map模拟实现

news2024/9/27 12:08:56

欢迎来到博主的专栏:c++编程
博主ID:代码小豪

文章目录

    • unorder_map的底层
    • insert
      • 迭代器
      • 成员访问函数
      • operator++
      • operator-\-

unordered_map是STL中的关联式容器之一,与常规的map有两点不同
(1)unordered是无序的意思,之所以取这名字,是因为与常规map迭代器前进的方向是有序的,而unordered_map的迭代器前进方向是无序的。

void test1()
{
	int a[] = { 11,25,21,1,6,9,16 };
	unordered_map<int, int> op;
	map<int, int> m;
	for (auto e : a)
	{
		op.insert(make_pair(e, e));
		m.insert(make_pair(e, e));
	}
	for (auto e : m)//遍历map容器
	{
		cout << e.first << ' ';//1 6 9 11 16 21 25
	}
	cout << endl;
	for (auto e : op)//遍历unordered_map
	{
		cout << e.first << ' ';//11 9 1 25 21 6 16
	}
}

(2)之所以造成这种差异,是因为unordered_map的底层用的是哈希表,而map的底层是红黑树。这是底层而造成的差异。

unorder_map的底层

关于哈希表的介绍,博主放在了数据结构专栏中,因此不再赘述。

由于STL标准库中的set和map共用一个hashtable底层(SGI版stl),因此博主将hashtable做了些许修改:

template<class key,class T,class keyofT>
class hash_tab
{
public:
	typedef T value_type;
	typedef hash_Node<value_type> Node;
	hash_tab()
	{
		_tab.resize(10);
	}

	~hash_tab()
	{
		for (size_t i=0;i<_tab.size();i++)
		{
			Node* cur = _tab[i];
			while (cur != nullptr)
			{
				Node* next = cur->_next;
				delete cur;
				cur = next;
			}
			_tab[i] = nullptr;
			_n = 0;
		}
	}

private:
	vector<Node*> _tab;
	size_t _n;
	keyofT kot;
};

由于map和set的数据不一样,set的数据是key类型的,而map的数据是pair<key,value>型的,因此需要一个key值提取器——keyofT。关于keyofT怎么用,博主在会在后续文章提到。

insert

unordered_map类被博主设计成这样,其成员为底层哈希表.

template<class key,class value>
class unordered_map
{
public:
	typedef pair<key, value> value_type;

	template<class key,class value>
	class unordered_mapkeyofT
	{
		const key& operator()(const value_type& data)const
		{
			return data.first;
		}
	};

private:
	myhash::hash_tab<key, value_type, unordered_mapkeyofT<key, value>> _hashtab;//底层哈希表
	};

如果使用了底层哈希表,那么insert可以直接复用_hashtab的insert函数。

pair<iterator, bool> insert(const value_type& data)
{
	return _hashtab.insert(data);
}

而unordered_map的erase,find操作都可以这样做,因此模拟实现unordered_map最重要的一步是设计出hashtab使用的迭代器。

迭代器

关于哈希的迭代器,博主是这样构思的,迭代器有两个成员,分别是指向当前哈希表的指针,以及一个指向该表的有效数据的指针。

在这里插入图片描述

template<class key,class T,class ref,class ptr,class keyofT>
struct hash_iterator
{
	typedef hash_Node<T> Node;
	typedef hash_tab<key, T, keyofT> hash;
	typedef hash_iterator self;

	hash_iterfator(Node* node,hash* tab)
	{
		_node = node;
		_tab = tab;
	}


	keyofT kot;
	Node* _node;//指向节点
	hash* _tab;//指向当前哈希表
};

begin()函数返回指向哈希表第一个有效数据的节点
在这里插入图片描述

Iterator begin()
{
	Node* cur = nullptr;
	for (int i = 0; i < _tab.size(); i++)
	{
		cur = _tab[i];
		if (cur != nullptr)
			return Iterator(cur, this);
	}
	return Iterator(cur, this);
}

end函数则返回nullptr作为结束标志。

Iterator end()
{
	return Iterator(nullptr, this);
}

最后加上const版本的begin和end。

const_Iterator begin() const
{
	Node* cur = nullptr;
	for (int i = 0; i < _tab.size(); i++)
	{
		cur = _tab[i];
		if (cur != nullptr)
			return Iterator(cur, this);
	}
	return Iterator(cur, this);
}

const_Iterator end()const
{
	return Iterator(nullptr, this);
}

成员访问函数

迭代器的成员访问函数也就是operator*和operator->.这很简单。

ref operator*()
{
	return _node->_data;
}

ptr operator->()
{
	return &operator*();
}

operator++

operator++让迭代器前进到下一个有效数据。做法如下:
(1)有限前进到同一个桶中的下一个有效数据的节点
(2)如果桶中不存在有效节点,就去找下一个有数据的哈希桶。

在这里插入图片描述
代码如下:

self operator++()
{
	if (_node->_next != nullptr)
	{
		_node = _node->_next;
	}
	else
	{
		size_t hashnum = kot(_node->_data) % _tab->_tab.size();
		hashnum++;
		while (hashnum < _tab->_tab.size())
		{
			Node* cur = _tab->_tab[hashnum];
			if (cur != nullptr)
			{
				_node = cur;
				return *this;
			}
			hashnum++;
		}
		_node = nullptr;//如果没找到,就返回end()标志
		return *this;
	}
}

operator--

operator--的操作如下:
(1)首先找到当前节点的映射地址
(2)判断该节点是否是该桶的第一个节点

若为否,则迭代器指向该节点的上一个节点

若为真,则迭代器指向上一个桶的最后一个节点
在这里插入图片描述
代码如下:

	self operator--()
	{
		int hashnum = kot(_node) % _tab->_tab.size();
		Node* cur = _tab->_tab[hashnum];

		if (cur != _node)
		{
			while (cur->_next != _node)
			{
				cur = cur->_next;
			}
			_node = cur;
			return *this;
		}
		else//cur==_node
		{
			for (int i = hashnum-1; i >= 0; i--)
			{
				cur = _tab->_tab[i];
				if (cur != nullptr)
				{
					while (cur->_next != nullptr)
					{
						cur = cur->_next;
					}
					_node = cur;
					return *this;
				}
			}
		}
	}

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

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

相关文章

AI与我同创诗:尝试让ai(智谱清言)参与我的诗创活动

ai伴学越久&#xff0c;契合度愈高&#xff0c;“泛滥”之诗情&#xff0c;幸得学伴共雕琢。让ai伴学久了&#xff0c;不知觉的&#xff0c;写诗也让ai帮衬了。此文收录“我共ai”的自创文稿&#xff0c;亦可作“ai诗集”。&#x1f60b; (笔记模板由python脚本于2024年09月03日…

企业微信中嵌套的h5应用调用微信扫码功能

企业微信官方文档 1.登录企业微信后台,管理员可操作,打开应用配置应用可信域名(必须配置,否则无法调用jsapi,可信域名必须有ICP备案且在管理端验证域名归属) 配置部署后的前台域名地址 配置可信域名,部署后的服务器域名(需备案认证) 当域名权限不够时需下载文件效验,将文件放…

网站开发:HTML + CSS - CSS选择器

1. 前言 CSS&#xff08;Cascading Style Sheets&#xff0c;层叠样式表&#xff09;是一种用于控制 HTML 文档样式和布局的语言。它为 Web 页面提供了许多功能&#xff0c;使开发者能够创建美观且功能丰富的用户界面。 提供了丰富的功能来控制网页的外观和布局&#xff0c;增…

掌握SQLAlchemy:Python数据库的魔法师

文章目录 掌握SQLAlchemy&#xff1a;Python数据库的魔法师背景&#xff1a;为什么选择SQLAlchemy&#xff1f;SQLAlchemy是什么&#xff1f;如何安装SQLAlchemy&#xff1f;五个简单的库函数使用方法1. 创建引擎2. 定义模型3. 创建会话4. 添加数据5. 查询数据 场景应用1. 多表…

大模型构建合作性的Agent,多代理框架MetaGpt

大模型构建合作性的Agent,多代理框架MetaGpt 前言 MetaGPT 框架将标准的操作程序(SOP)与基于大模型的多智能体相结合,使用标准操作程序来编码提示,确保协调结构化和模块化输出。 MetaGPT 允许 Agent 在类似流水线的范式中扮演多中角色,通过结构化的 Agent 协作和强化领…

Android Studio 加载多个FLutter项目

按顺序操作即可 选择工程 选择Modules, 导入 module 选中创建module 选择要导入的目录&#xff0c;只选择主目录&#xff0c;下面的文件不要选 添加完成&#xff0c;点击ok后&#xff0c;会进行导入 最终导入成功

三星称霸全球市场,但它在中国市场再受打击,将进一步收缩业务

韩国媒体报道指三星已计划进一步收缩中国业务&#xff0c;将中国的销售和生产部门人员减少一部分&#xff0c;其中销售人员计划减少8%左右&#xff0c;显示出它在中国市场继续面临打击&#xff0c;对于这家在全球市场领先地位仍然稳固的企业来说&#xff0c;它在中国市场无疑又…

OpenCV结构分析与形状描述符(8)点集凸包计算函数convexHull()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 查找一个点集的凸包。 函数 cv::convexHull 使用斯克拉斯基算法&#xff08;Sklansky’s algorithm&#xff09;来查找一个二维点集的凸包&#…

Wyn 商业智能V8.0 新版本来袭,解锁“智造”的无限可能

Wyn商业智能V8.0 版本全新发布&#xff0c;聚焦制造业数字化升级痛点&#xff0c;深度赋能制造业数字化转型升级之路&#xff0c;从无缝集成物联网海量数据&#xff0c;到构建可视化实时分析、监控与预警大屏&#xff0c;全面打通生产制造全生命周期的数据脉络&#xff0c;为您…

免费OCR 文字识别工具

免费&#xff1a;本项目所有代码开源&#xff0c;完全免费。 方便&#xff1a;解压即用&#xff0c;离线运行&#xff0c;无需网络。 高效&#xff1a;自带高效率的离线OCR引擎&#xff0c;内置多种语言识别库。 灵活&#xff1a;支持命令行、HTTP接口等外部调用方式。 功能…

hiprint打印/jsPDF使用/html2canvas

最初我知道hiprint.print是可以打印双模板的&#xff0c;于是查看hiprint.print的源码发现底层实现是this.getHtml(t).hiwprint,于是断点查看getHtm的实现&#xff0c;得知它是遍历我们对print传参的list&#xff0c;利用list中模板对象的getHtml()方法得到模板的dom对象&#…

论文120:Giga-SSL: Self-supervised learning for gigapixel images (2023, CVPR, 开源)

文章目录 1 要点2 方法2.1 算法设计2.2 设计选择 1 要点 题目&#xff1a;用于千兆像素图像的自监督学习 (Giga-SSL: Self-Supervised Learning for Gigapixel Images) 代码&#xff1a;https://github.com/trislaz/gigassl 研究目的&#xff1a; 现有的WSI分类方法依赖于有…

告别格式不兼容烦恼!ape转换mp3,分享3个简单方法

各位读者们&#xff0c;你们是否有过这种体验&#xff1a;满怀期待地在网上下载一首好听的歌曲&#xff0c;结果怎么点击手机都播放不了&#xff0c;定睛一看&#xff0c;弹窗显示“无法播放该音频文件”。这是为什么呢&#xff1f;原来那首歌的音频格式是ape&#xff0c;不被手…

2024年全国大学生数学建模C题解题思路

C 题 农作物的种植策略 gzh 大学竞赛君 根据乡村的实际情况&#xff0c;充分利用有限的耕地资源&#xff0c; 因地制宜&#xff0c;发展有机种 植产业&#xff0c;对乡村经济 的可持续发展具有重要的现实意义 。选择适宜的农作物&#xff0c; 优化种植策略&#xff0c;有利于方…

认识正则表达式

为什么要学习正则表达式 因为爬虫需要&#xff01;&#xff01;&#xff01; 一般来说爬虫需要四个主要步骤&#xff1a; 明确目标 (要知道你准备在哪个范围或者网站去搜索)爬 (将所有的网站的内容全部爬下来)取 (去掉对我们没用处的数据)处理数据&#xff08;按照我们想要的方…

Codeforces Round 967 (Div. 2)(A,B,C,D)

A Make All Equal 题意 给定一个序列,每次如果a[i]<a[i1]则可以删除这两个的任意一个,问找出使a中所有元素相等所需的最小删除次数 思路 最小的删除次数就是保留相同数字最多的那个数的删除次数,无论如何都可以保留这个数,因为假如是3334那么可以根据3和4把4删了,假如是3…

学习记录:js算法(二十六):回文链表

文章目录 回文链表我的思路网上思路 总结 回文链表 给你一个单链表的头节点 head &#xff0c;请你判断该链表是否为回文链表。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 图一 图二 示例 1&#xff1a;&#xff08;图一&#xff09; 输入&…

数仓工具—Hive语法之URL 函数

hive—语法—URL 函数 业务需求中,我们经常需要对用户的访问、用户的来源进行分析,用于支持运营和决策。例如我们经常对用户访问的页面进行统计分析,分析热门受访页面的Top10,观察大部分用户最喜欢的访问最多的页面等: 又或者我们需要分析不同搜索平台的用户来源分析,统…

SpringBoot开发——结合Thymeleaf模板整合HTML

文章目录 一、 Thymeleaf介绍二、Springboot整合thymeleaf模板1、实现步骤1)创建一个Springboot项目2) 创建application.yml文件3)创建HTML文件4)编写controller文件5)启动Spring Boot2、Thymeleaf常用语法赋值、拼接条件判断: if/unless循环URL三元运算switch基本对象内…

Java报错处理系列之:Unable to make protected void java.util.ResourceBundle.setParent

Java报错处理系列之&#xff1a;Internal error : Unable to make protected void java.util.ResourceBundle.setParent accessible: module java.base does not "opens java.util" to unnamed module 7f1302d6 一、完整报错二、报错原因三、解决方法四、更多报错解决…