波奇学C++:哈希

news2024/9/28 13:28:43

哈希本质是的值和位置建立关联起来,这种关联关系就是哈希函数

示例:除留余数:对输入的数字取模。

哈希冲突:多个不同的值指向同一个位置

解决方法:

闭散列:开发地址法。

把24放在下一个位置

哈希桶

闭散列法

闭散列的负载因子:表元素个数/散列表长度(size),当负载因子达到一定范围时就进行扩容。

扩容会涉及重新映射,取模的范围变大了。

闭散列的元素搜索:闭散列的元素搜索到空截止,要搜索的值只可能往后延,不可能提前,所以如果为空,说明没有。

闭散列的删除:不能直接置空,而是要设置一个状态值表示是否删除。

enum STATE
	{
		EXIST,
		EMPTY,
		DELETE
	};

对于其他类型string,可以选择仿函数来取哈希值,算法上的难点是取哈希值的方式。

其中一个算法

	template<>
	struct DefaultHashFunc<string>
	{
		size_t operator()(const string& str)
		{
			// BKDR
			size_t hash = 0;
			for (auto ch : str)
			{
				hash *= 131;
				hash += ch;
			}

			return hash;
		}
	};

完整代码

namespace myhashtable {
	enum STATE
	{
		EXIST,
		EMPTY,
		DELETE
	};
	template<class K, class V>
	struct HashData
	{
		pair<K, V> _kv;
		STATE _state = EMPTY;

	};
	template<class K>
	struct DefaultHashFunc
	{
		size_t operator()(const K& key)
		{
			return (size_t)key;
		}
	};
	template<>
	struct DefaultHashFunc<string>
	{
		size_t operator()(const string& str)
		{
			// BKDR
			size_t hash = 0;
			for (auto ch : str)
			{
				hash *= 131;
				hash += ch;
			}

			return hash;
		}
	};

	template<class K, class V,class HashFunc=DefaultHashFunc<K>>
	class HashTable
	{
	public:
		HashTable()
		{
			_table.resize(10);
		}
		bool Insert(const pair<K, V>& kv)
		{
			//扩容
			if ((double)_n * 10 / (double)_table.size() >= 0.7)
			{
				size_t newSize = _table.size() * 2;
				// 扩容以后映射关系变了
				HashTable<K, V> newHT;
				newHT._table.resize(newSize);
				// 遍历旧表的数据插入新表就可以了
				for (size_t i = 0; i < _table.size(); i++)
				{
					if (_table[i]._state == EXIST)
					{
						newHT.Insert(_table[i]._kv);
					}
				}
				_table.swap(newHT._table);
			}
			HashFunc hf;
			size_t hashi =hf( kv.first) % _table.size();
			while (_table[hashi]._state == EXIST)
			{
				++hashi;
				hashi %= _table.size();
			}
			_table[hashi]._kv = kv;
			_table[hashi]._state = EXIST;
			++_n;
			return true;
		}
		HashData<const K, V>* Find(const K& key)
		{
			HashFunc hf;
			size_t hashi = hf(key) % _table.size();
			while (_table[hashi]._state != EMPTY)
			{
				if (_table[hashi]._state == EXIST
					&& _table[hashi]._kv.first == key)
				{
					return (HashData<const K, V>*) & _table[hashi]._kv;
				}
				++hashi;
				hashi %= _table.size();
			}
			return nullptr;

		}
		bool Erase(const K& key)
		{
			HashData<const K, V>* ret = Find(key);
			if (ret)
			{
				ret->_state = DELETE;
				--_n;
				return true;
			}
			return false;
		}
	private:
		vector<HashData<K, V>> _table;
		size_t _n =0;
	};
}

哈希桶方法

关键点:哈希表存节点地址,用单链表存冲突的哈希值

namespace bush_bucket
{
	template<class K,class V>
	struct HashNode
	{
		pair<K, V> _kv;
		HashNode<K, V>* _next;
		HashNode(const pair<K, V> kv)
		{
			_kv = kv;
			_next = nullptr;
		}
	};
	template<class K,class V>
	class HashTable
	{
		typedef HashNode<K, V> Node;
	public:
		HashTable()
		{
			
			_table.resize(10,nullptr);
		}
		~HashTable()
		{
			for (size_t i= 0; i < _table.size(); i++)
			{
				Node* cur = _table[i];
				while (cur)
				{
					Node* next = cur->_next;
					delete cur;
					cur = next;
				}
				_table[i] = nullptr;
			}
		}
		bool Insert(const pair<K, V>& kv)
		{
			if (Find(kv.first))
			{
				return false;
			}
			// 扩容
			if (_n == _table.size())
			{
				size_t newSize = _table.size()*2;
				vector<Node*> newTable;
				newTable.resize(newSize, nullptr);
				for (size_t i = 0; i < _table.size(); i++)
				{
					Node* cur = _table[i];
					while (cur)
					{
						Node* next = cur->_next;
						size_t hashi = cur->_kv.first % newSize;
						cur->_next = newTable[hashi];
						newTable[hashi] = cur;
						cur = next;
					}
					_table[i] = nullptr;
				}
				_table.swap(newTable);
			}
			size_t hashi = kv.first % _table.size();
			Node* newnode = new Node(kv);
			newnode->_next = _table[hashi];
			_table[hashi] = newnode;
			++_n;
			return true;
		}
		Node* Find(const K& key)
		{
			size_t hashi = key% _table.size();
			Node* cur = _table[hashi];
			while (cur)
			{
				if (cur->_kv.first == key)
				{
					return cur;
				}
				
				cur = cur->_next;
			}
			return nullptr;
		}
		bool Erase(const K& key)
		{
			size_t hashi = key % _table.size();
			Node* prev = nullptr;
			Node* cur = _table[hashi];
			while (cur)
			{
				if (cur->_kv.first == key)
				{
					if (prev == nullptr)
					{
						_table[hashi] = cur->_next;
					}
					else
					{
						prev->_next = cur->_next;
					}
					delete cur;
					return true;
				}
				prev = cur;
				cur = cur->_next;
			}
			return false;
		}
		void Print()
		{
			for (int i = 0; i < _table.size(); i++)
			{
				printf("[%d]->", i);
				Node* cur = _table[i];
				while (cur)
				{
					cout << cur->_kv.first << "->";
					cur = cur->_next;
				}
				printf("null");
				printf("\n");
			}
		}
	private:
		vector<Node*> _table; //指针数组
		size_t _n=0;
	};
}

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

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

相关文章

NNDL:作业3

在Softmax回归的风险函数(公式(3.39))中如果加上正则化项会有什么影响? (1) 在 Softmax 回归的风险函数中加入正则化项会对模型的训练产生影响。正则化项的作用是对模型的复杂度进行惩罚&#xff0c;防止过拟合的发生。 (2) 原书公式为&#xff1a; 在加入正则化后损失函数…

STM32单片机入门学习(六)-光敏传感器控制LED

光敏传感器模块和LED接线 LED负极接B12,正极接VCC 光敏传感模块一DO端接B13,GND接GND&#xff0c;VCC接VCC,AO不接。 如图&#xff1a; 主程序代码&#xff1a;main.c #include "stm32f10x.h" #include "Delay.h" //delay函数所在头文件 #include …

Python中套接字实现服务端和客户端3-3

3 创建客户端的步骤 创建客户端的步骤如图5所示。 图5 创建客户端的步骤 从图5可以看出&#xff0c;对于客户端来说&#xff0c;首先创建套接字&#xff0c;之后通过创建的套接字去连接服务端&#xff0c;如果连接成功&#xff0c;则继续通过该套接字向服务端发送数据&#x…

扩展windows 10 文件夹文件路径位数

Enable Long Paths in Windows 10, Version 1607, and Later PowerShell Copy New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force 管理员权限运行 PowerShell…

【开源电商网站】(2),使用docker-compose和dockerfile进行配置,设置自定义的镜像,安装插件,增加汉化包,支持中文界面汉化。

项目相关代代码地址 相关内容&#xff1a; https://blog.csdn.net/freewebsys/category_12461196.html 原文地址&#xff1a; https://blog.csdn.net/freewebsys/article/details/133666433 包括以下运行的详细代码&#xff1a; https://gitee.com/study-demo-all/oscommerc…

将cpu版本的pytorch换成gpu版本

1.首先激活虚拟环境 winRcmd 打开dos命令窗口 查看虚拟环境列表 conda env list 激活虚拟环境 2.将原来的pytorch_cpu版本换成gpu版本 注意&#xff1a;安装gpu版本的pytorch时并不需要先卸载原来的cpu版本pytorch,安装时会自己替换的 打开pytorch官网查看以前版本 Previo…

vant组件安装之后导入所有组件报错

问题&#xff1a;引入vant报错(Module build failed (from ./node_modules/postcss-loader/src/index.js): 解决办法&#xff1a;在node_modules里面找到 vant目录下面的lib里面的 index.css&#xff1b; 在url前面加上空格即可

MongoDB 笔记

1 insert 、create、save区别 insert: 主键不存在则正常插入&#xff1b;主键已存在&#xff0c;抛出DuplicateKeyException 异常 save: 主键不存在则正常插入&#xff1b;主键已存在则更新 insertMany&#xff1a;批量插入&#xff0c;等同于批量执行 insert create&#x…

地下城堡3最强英雄搭配,地下城堡3公认最强阵容

在地下城堡3中&#xff0c;组建一支最强的阵容是玩家们追求的目标之一。通过合理的角色搭配和战术配合&#xff0c;你可以打造一个无敌的团队&#xff0c;在战斗中几乎无往而不胜。下面是地下城堡3公认最强阵容搭配攻略&#xff0c;让你在游戏中轻松征战各个副本和挑战。 关注【…

基于 LSTM 进行多类文本分类(附源码)

NLP 的许多创新是如何将上下文添加到词向量中。一种常见的方法是使用循环神经网络。以下是循环神经网络的概念&#xff1a; 他们利用顺序信息。 他们可以捕捉到到目前为止已经计算过的内容&#xff0c;即&#xff1a;我最后说的内容会影响我接下来要说的内容。 RNNs 是文本和…

一次性读懂Mendix的库间“数据同步”功能

Data sync&#xff0c;对于那些深谙其道的技术高手而言&#xff0c;意义不言自明。然鹅对整天在村工厂里打螺丝的我来说&#xff0c;却经历了一段难捱的时期。时至今日&#xff0c;我仍然时不时地选择性地遗忘某些概念和技术点。因此&#xff0c;本文章记录我之前一点实操的心得…

【测试】robotframework安装

目录 python安装 pip一系列安装 运行效果 参考文档 python安装 注意管理员权限安装&#xff0c;不然2503的错误 。 pip一系列安装 pip install robotframework pip install wxPython pip install robotframework-ride 运行python ride.py pip install setuptools 解决…

125KHz低频接收唤醒芯片:Si3933(TSSOP16)

Si3933 具有内部时钟产生器&#xff0c;可使用晶体振荡器或者RC振荡器&#xff0c;也可以使用外部时钟。 Si3933 是一款三通道的D功耗ASK接 收机&#xff0c;可用于检测15KHz-150KHz低频载波频率的数字信号&#xff0c;并产生唤醒信号。内部集成的校验器用于检测 16 位或 32 位…

双态IT乌镇大会 | 首批《数据中心业务连续性等级评价准则》试点单位将诞生

2023年10月13日-15日&#xff0c;由ITSS分会、证券基金行业信息技术应用创新联盟指导&#xff0c;ITSS数据中心运营管理组&#xff08;DCMG&#xff09;、双态IT论坛、智能运维国标工作组主办&#xff0c;ITSS媒体组、AI范儿协办的“2023第六届双态IT乌镇用户大会”将于浙江乌镇…

SpringBoot采用Dynamic-Datasource方式实现多JDBC数据源

目录 1. Dynamic-Datasource实现多JDBC数据源配置1.1 特性1.2 Mysql数据准备2.2 通过Dynamic-Datasource实现多JDBC数据源2.2.1 pom.xml依赖 2.2.2 application.properties配置2.2.3 使用DS注解选择DataSource2.2.4 使用Transactional DSTransactional实现事务 2.3 动态数据源…

下一代架构设计:云原生、容器和微前端的综合应用

文章目录 云原生&#xff1a;构建可弹性扩展的应用1. 微服务架构2. 容器化3. 自动化和自动扩展 容器化和云原生的结合1. 一致性和可移植性2. 弹性和可伸缩性3. 快速部署和更新4. 资源利用率 微前端&#xff1a;前端架构的演进1. 微前端应用2. 统一的外壳应用3. 独立部署 云原生…

TikTok在跨境电商中的作用:挖掘潜在客户的最佳途径

​随着全球数字化浪潮的不断发展&#xff0c;跨境电商行业也经历了巨大的变革。传统的市场营销渠道已经不再足够&#xff0c;企业们需要不断探寻新的方法来吸引潜在客户。在这个过程中&#xff0c;社交媒体平台TikTok逐渐崭露头角&#xff0c;成为了吸引潜在客户的一个选择。本…

[PwnThyBytes 2019]Baby_SQL - 代码审计+布尔盲注+SESSION_UPLOAD_PROGRESS利用

[PwnThyBytes 2019]Baby_SQL 1 解题流程1.1 分析1.2 解题 2 思考总结 1 解题流程 1.1 分析 此题参考文章&#xff1a;浅谈 SESSION_UPLOAD_PROGRESS 的利用 访问正常来讲用ctf-wscan是能扫出source.zip文件的&#xff0c;且F12后提示了有source.zip&#xff0c;那我们就下载…

Apache POI使用

1.导入坐标 <!-- poi --><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>${poi}</version></dependency><dependency><groupId>org.apache.poi</groupId><a…

elasticSearch7.9数据占用磁盘存储空间情况

最近&#xff0c;在VMware Workstation虚拟机上安装了es7.9&#xff0c;单节点的es&#xff0c;不是集群&#xff0c;然后建了一个索引&#xff08;包含3个分片和一个副本&#xff09;&#xff0c;插入了500万条数据&#xff0c;占据磁盘空间17G。如下图&#xff1a; 索引的字…