数据结构: 哈希桶

news2024/11/23 21:49:14

目录

1.概念

2.模拟实现

2.1框架

2.2哈希桶结构

2.3相关功能

Modify

--Insert

--Erase

--Find

2.4非整型数据入哈希桶

1.仿函数

2.BKDR哈希


1.概念

具有相同地址的key值归于同一集合中,这个集合称为一个桶,各个桶的元素通过单链表链接

2.模拟实现

2.1框架

a.写出哈希桶的结构: hash_node  + hash_table     节点  +   指针数组

b.思路: 增删查改的实现 + 扩容  

c.使用除留余数法获得在哈希表中的位置~~>将非整型数据转换为整型数据~~>提供仿函数

2.2哈希桶结构

哈希桶本质是一个指针数组,里面存放的是指针,指向一个链表~~>使用vector来存放  +  n(负载因子)

namespace HashBucket 
{
	//1.节点
	template<class T>
	struct HashNode 
	{
		HashNode<T>* _next;
		T _data;
		//构造函数
		HashNode(const T& data)
			:_next(nullptr)
			,_data(data)
		{}
	};

	//2.哈希表
	template<class T>
	class HashTable 
	{
		typedef HashNode<T> Node;
	public:
		//接口
	private:
		vector<Node>* _tables;
		size_t n = 0; //有效数据个数
	};
}

2.3相关功能

Modify

--Insert

思路:

1.判断是否需要扩容

        a.扩容~~>将原来的数据移动到新开辟的空间

        b.不扩容~~>直接头插

2.头插

        a.计算这个值在哈希表中的位置

        b.单链表的头插

        c.更新hash_table

--将旧数据移动到新开辟的空间

方式1:复用insert~~>额外开辟新节点 + 释放旧的空间

方式2:直接挪动

        a.开辟新空间(创建新表)

        b.遍历原链表~~>取节点下来头插(保存下一个节点 + 重新计算hashi + 头插)

        c.交换新旧表

        

--单链表的头插:

代码:

		bool Insert(const T& data) 
		{
			//1.扩容检查
			if (n == _tables.size()) 
			{
				size_t newsize = _tables.size() == 0 ? 10 : 2 & _tables.size();
				vector<Node*> newtables(newsize, nullptr);	//创建新表
				//将原来的数据挪动到新表
				for (auto& cur : _tables) 
				{
					while (cur) 
					{
						//保存下一个节点
						Node* next = cur->_next;
						//重新计算在哈希桶中的位置
						size_t hashi = (cur->_data) % newtables.size();
						//放进新桶
						cur->_next = newtables[hashi];
						newtables[hashi] = cur;
						cur = next;
					}
				}
				//交换
				_tables.swap(newtables);
			}

			//2.头插数据
			Node* newnode = new Node(data);      //创建节点
			size_t hashi = data % _tables.size();//计算在在个哈希桶
			newnode->_next = _tables[hashi];	 
			_tables[hashi] = newnode;
			++n;

			return true;
		}

效果:

           

--Erase

思路:

1.计算data在哪个哈希桶

2.删除节点

        a.头删~~>更新头

        b.非头删除~~>找pre链接next

代码:

		bool Erase(const T& data) 
		{
			//1.计算在哪个哈希桶
			size_t hashi = data % _tables.size();
			//2.删除节点
			Node* pre = nullptr, * cur = _tables[hashi];
			while (cur) 
			{
				//记录下一个节点
				Node* next = cur->_next;
				if (cur->_data == data) 
				{
					//头删
					if (pre == nullptr) 
					{
						delete cur; cur = nullptr;
						_tables[hashi] = next;
						return true;
					}
					//非头删
					else 
					{
						pre->_next = next;
						delete cur; cur = nullptr;
						return true;
					}
				}
				//没找到继续往后找
				pre = cur;
				cur = cur->_next;
			}
			return false;
		}

效果

--非头删:

--头删

--Find

思路:

如果哈希表没有元素,直接返回

1.计算在哪个哈希桶

2.遍历这个哈希桶,看有没有这个值

代码:

		Node* Find(const T& data) 
		{
			//如果这个哈希表为空, 直接返回
			if (_tables.size() == 0)return nullptr;

			//1.计算在哪个哈希桶
			size_t hashi = data % _tables.size();
			//2.遍历这个桶,找data
			Node* cur = _tables[hashi];
			while (cur) 
			{
				if (cur->_data == data)
					return cur;
				cur = cur->_next;
			}
			//遍历完都没有找到
			return nullptr;
		}

效果:

2.4非整型数据入哈希桶

由于哈希桶是采用除留余数法 ~~>  算在哪个哈希桶 ~~> 必须是整型数据

1.仿函数

使用仿函数将非整型数据转换为整型

代码:

	//仿函数
	template<class T>
	struct HashFunc 
	{
		size_t operator()(const T& data) 
		{
			return data;
		}
	};

2.BKDR哈希

若数据类型是string, "abc" 与"cba"通过相同的哈希函数计算出来的hashi,会相同

~~>引入BKDR哈希, 每次算一个字符的时候, hash *= 31 ~~>让计算出来的hashi尽可能不同

代码:

	//模板特化
	template<>
	struct HashFunc<string> 
	{
		size_t operator()(const string& s) 
		{
			size_t hash = 0;
			for (auto ch : s) 
			{
				hash += ch;
				hash *= 31;
			}
			return hash;
		}
	};

效果:

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

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

相关文章

oracle数据导出exp导入imp

Oracle的exp/imp命令用于实现对数据库的导出/导入操作&#xff1b; exp命令用于把数据从远程数据库服务器导出至本地&#xff0c;生成dmp文件&#xff1b; imp命令用于把本地的数据库dmp文件从本地导入到远程的Oracle数据库。 一、获取帮助信息 exp/imp helpy 二、数据导出 1…

打破边界,一触即达——全新跨境电商业态,一键开启全球贸易新时代!

随着全球电子商务的飞速发展&#xff0c;跨境电商已成为连接国内外市场的桥梁。为了满足商家日益增长的海外拓展需求&#xff0c;我们重磅推出跨境电商源码商城&#xff0c;融合商家一键铺货、代理商后台、供货商后台、商品采集、短视频、直播、社交、分销、积分、多语言、国际…

阿里云双11优惠:云服务器1年99元,新老同享,续费同价!

阿里云2核2G3M带宽99元服务器新老用户同享&#xff0c;续费不涨价&#xff0c;99元即可续费&#xff0c;可以续费到2027年&#xff0c;相当于396元买4年&#xff0c;阿里云百科aliyunbaike.com来详细说下阿里云99元服务器配置、购买条件、优惠价格和续费攻略&#xff1a; 阿里…

js获取地址中携带的省市区

match() 方法可在字符串内检索指定的值&#xff0c;或找到一个或多个正则表达式的匹配。 match() 方法将检索字符串 String Object&#xff0c;以找到一个或多个与 regexp 匹配的文本。这个方法的行为在很大程度上有赖于 regexp 是否具有标志 g。如果 regexp 没有标志 g&#x…

图形界面应用案例——关灯游戏(以及扩展)(python)

7.8 图形界面应用案例——关灯游戏 题目: [案例]游戏初步——关灯游戏。 关灯游戏是很有意思的益智游戏,玩家通过单击关掉(或打开)一盏灯。如果关(掉(或打开)一个电灯,其周围(上下左右)的电灯也会触及开关,成功地关掉所有电灯即可过关。 图7-43 关灯游戏运行效…

阿里云服务器登录、安装MySql、配置Python、GO环境

1、刚购买的云服务如何登录 刚购买的ECS没有默认密码&#xff0c;需要先设置一下登录的密码。选中实例&#xff0c;右上角的全部操作-->重置实例密码 如果想通过SSH登录&#xff0c;则一定要勾选开启 修改之后ssh root你机器的ip&#xff0c;输入密码就可以愉快的开始你的操…

在Ubuntu下安装Redis

文章目录 前言一、配置JAVA运行环境二、Ubuntu下安装Redis1.安装c语言编译环境2.下载解压Redis3.make编译4.启动Redis4.运行Redis 三、性能测试总结 前言 版本 jdk版本&#xff1a;jdk-17_linux-x64_bin 地址&#xff1a;https://www.oracle.com/cn/java/technologies/downloa…

chatglm3-6b部署及微调

chatglm3-6b部署及微调 modelscope: https://modelscope.cn/models/ZhipuAI/chatglm3-6b/filesgithub: https://github.com/THUDM/ChatGLM3镜像: ubuntu20.04-cuda11.8.0-py38-torch2.0.1-tf2.13.0-1.9.4v100 16G现存 单卡 安装 软件依赖 pip install --upgrade pippip ins…

MySQL基础架构详解

概述 我们学习东西&#xff0c;都不应该是先去了解细节&#xff0c;而是应该窥其全貌&#xff0c;这样才能从高纬度去理解问题&#xff0c;同样我们学习mysql也是一样的&#xff0c;我们应该先了解整个mysql架构&#xff0c;及来龙去脉&#xff0c;才能更好的掌握它。下面我们开…

阿里云 :推出通义大模型编码助手产品【通义灵码】

本心、输入输出、结果 文章目录 阿里云 &#xff1a;推出通义大模型编码助手产品【通义灵码】前言通义灵码简介主要功能主要功能点 支持的语言和 IDEjetbrains IDEA 安装计费相关弘扬爱国精神 阿里云 &#xff1a;推出通义大模型编码助手产品【通义灵码】 编辑&#xff1a;简简…

java实现wav的重采样

在处理一些用户上传的音频的时候&#xff0c;往往根据用户的设备不通&#xff0c;文件格式难以统一&#xff0c;尤其是涉及到算法模型相关的&#xff0c;更是令人头疼&#xff0c;这里提供两种思路解决这个问题。 不借助三方库 这种采用的是javax.sound.sampled下的包来实现&a…

数据结构之顺序表的实现(详解!附完整代码)

线性表 线性表&#xff08;linear list&#xff09;是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构 常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串… 线性表在逻辑上是线性结构&#xff0c;也就说是连续的一条直线。但是在物理结…

十五、W5100S/W5500+RP2040树莓派Pico<TFTP Client>

文章目录 1 前言2 简介2 .1 什么是TFTP&#xff1f;2.2 TFTP的优点2.3 TFTP和FTP对比2.4 TFTP应用场景 3 WIZnet以太网芯片4 ARP网络设置示例概述以及使用4.1 流程图4.2 准备工作核心4.3 连接方式4.4 主要代码概述4.5 结果演示 5 注意事项6 相关链接 1 前言 一般来说&#xff0…

金蝶云星空BOS设计器中基础资料字段属性“过滤”设置获取当前界面的基础资料值作为查询条件

文章目录 金蝶云星空BOS设计器中基础资料字段属性“过滤”设置获取当前界面的基础资料值作为查询条件背景说明业务需求格式BOS配置 金蝶云星空BOS设计器中基础资料字段属性“过滤”设置获取当前界面的基础资料值作为查询条件 背景说明 序列号档案是基础资料&#xff0c;资料里…

delphi程序启动时带参数运行的例子

这里有一个坑&#xff0c;就是参数会减少一个 //需要引用这个单元 uses shellapiprocedure TForm1.Button5Click(Sender: TObject); varParams: string; begin //由于第三个参数不会显示&#xff0c;需要额外的多补充一个参数&#xff0c;而且第一个参数会变成程序的运行路径P…

什么是超级托斯卡纳葡萄酒?

超级托斯卡纳葡萄酒通常被认为是在托斯卡纳用国际葡萄品种制成的葡萄酒&#xff0c;如赤霞珠、品丽珠或梅洛&#xff0c;而不是传统的托斯卡纳葡萄桑娇维塞。来自云仓酒庄品牌雷盛红酒分享这些葡萄酒可能包含一些桑娇维塞&#xff0c;但这通常不是混合中的主要葡萄。这些大胆的…

工程车云管家|叉车智能管家安卓主板方案

工程车云管家是一款功能强大的设备管理和调度系统&#xff0c;它可以实时追踪工程车或机械设备的地理位置、视频、行驶轨迹、油位油耗、工作时长和地点、以及运行状况等信息&#xff0c;并将这些数据通过云平台存储、分析&#xff0c;并发送到管理者的手机上。这使得管理者能够…

Windows安装svn命令

1、svn命令下载地址 https://www.visualsvn.com/downloads/; 2、安装svn命令 3、测试svn命令是否安装成功

Java修仙传之神奇的ES2(巧妙的查询及处理)

SDL语句查询 查询的基本语法 GET /indexName/_search {"query": {"查询类型": {"查询条件": "条件值"}} } 根据文档id查询 #查询文档 GET hotel/_doc/36934 查询所有 会弹出该索引库下所有文档// 查询所有 GET /indexName/_searc…

quickapp_快应用_快应用组件

快应用组件 web组件web页面与快应用页面通信网页接收/发送消息网页接收消息 快应用页面接收/发送消息给网页发送消息 通信前提- trustedurl web组件 作用&#xff1a;用于显示在线的 html 页面(可以嵌入三方页面或者某些不太重要的页面) 缺点&#xff1a;打开会比原生慢一点&…