哈希原理实现

news2024/11/26 12:20:31

本节主要看源代码实现

哈希特点

哈希(Hashing)是一种将数据映射到固定大小的表中以实现快速查找的数据结构和算法方法。哈希的主要特点包括:

1. 高效的查找、插入和删除

  • 时间复杂度:哈希表通常提供近乎常数时间的查找、插入和删除操作,理想情况下为 ( O(1) )。
  • 性能:由于通过哈希函数直接计算位置,数据可以迅速定位,减少了需要遍历的数据量。

2. 哈希函数

  • 定义:哈希函数是将输入数据(键)映射到哈希表中的一个位置的函数。
  • 特点
    • 确定性:相同的输入始终会映射到相同的位置。
    • 均匀分布:理想的哈希函数将输入数据均匀分布到哈希表的各个槽位,减少冲突的可能性。
    • 快速计算:哈希函数应当能够快速计算,以避免对性能的影响。

3. 冲突处理

  • 冲突:当两个或更多的键被映射到哈希表的同一位置时,称为冲突。
  • 处理方法
    • 链式地址法(Separate Chaining):使用链表或其他数据结构处理同一位置的多个键。
    • 开放地址法(Open Addressing):通过探测策略(如线性探测、二次探测、双重哈希)寻找其他空槽位。

4. 负载因子

  • 定义:负载因子是哈希表中元素数量与表大小的比率。
  • 影响
    • 性能:负载因子较高时,冲突概率增加,操作性能可能下降。
    • 动态调整:通常会在负载因子超过某个阈值时,进行哈希表的扩展和再哈希操作,以保持性能。

开放寻址法

概念:所有元素都存储在哈希表的数组中,冲突发生时,使用探测序列寻找下一个可用位置。

hash节点:

	enum State
	{
		EXIST,
		EMPTY,
		DELETE
	};

	template<class K, class V>
	struct HashData
	{
		pair<K, V> _kv;
		State _state = EMPTY;
	};

扩容代码

负载因子保证哈希表永远有剩余空间:负载因子过大则扩容

因子过大,哈希表扩容时,不能只是改变vector.size(会改变映射关系)

应新申请更大size的hashmap,后交换this&newhasnmap

// 扩容
			if (_n * 10 / _tables.size() >= 7)
			{
				//vector<HashData<K, V>> newTables(_tables.size() * 2);
				 遍历旧表, 将所有数据映射到新表
				 ...
				//_tables.swap(newTables);

				HashTable<K, V, Hash> newHT;
				newHT._tables.resize(_tables.size() * 2);
				for (size_t i = 0; i < _tables.size(); i++)
				{
					if (_tables[i]._state == EXIST)
					{
						newHT.Insert(_tables[i]._kv);  //方法复用, 自动正确插入
					}
				}

				_tables.swap(newHT._tables);   //nb swap
			}

key不是int:先将key映射成int

自定义仿函数
struct StringHashFunc
	{
		size_t operator()(const string& s)
		{
			size_t hash = 0;
			for (auto e : s)
			{
				hash *= 31;
				hash += e;
			}

			return hash;
		}
	};
特化模板

(可默认调用, 省去传递仿函数类)

template<class K>
struct HashFunc
{
	size_t operator()(const K& key)
	{
		return (size_t)key;
	}
};

// 特化
template<>
struct HashFunc<string>
{
	size_t operator()(const string& key)
	{
		size_t hash = 0;
		for (auto e : key)
		{
			hash *= 31;
			hash += e;
		}

		return hash;
	}
};

对应默认调用

//当k为string时, Hash默认为特化后的类
template<class K, class V, class Hash = HashFunc<K>>
	class HashTable
	{
	public:
		HashTable()
		{
			_tables.resize(10);
		}
        ....
    }

 

拉链法:(哈希桶)

库里方法就是哈希桶实现哈希表

每个vector节点存一个链表头结点

单向链表,插入方便(头插)

再优化的话,可把节点换为map地址,防止一条链表过长影响效率

扩容时直接插入原节点,防重复删除又申请相同节点

扩容代码

// 负载因子==1扩容
			if (_n == _tables.size())
			{
                //重复delete & new, 不如直接转移
				/*HashTable<K, V> newHT;
				newHT._tables.resize(_tables.size() * 2);
				for (size_t i = 0; i < _tables.size(); i++)
				{
					Node* cur = _tables[i];
					while(cur)
					{
						newHT.Insert(cur->_kv);
						cur = cur->_next;
					}
				}

				_tables.swap(newHT._tables);*/
                
                // 推荐写法:将原有各节点转移到new的hashmap, 省去了delete&new
				vector<Node*> newtables(_tables.size() * 2, nullptr);
				for (size_t i = 0; i < _tables.size(); i++)
				{
					Node* cur = _tables[i];
					while (cur)
					{
						Node* next = cur->_next;

						// 旧表中节点,挪动新表重新映射的位置
						size_t hashi = hs(cur->_kv.first) % newtables.size();
						// 头插到新表
						cur->_next = newtables[hashi];
						newtables[hashi] = cur;
						
						cur = next;
					}

					_tables[i] = nullptr;
				}

				_tables.swap(newtables);
			}

类模板特化

template<class K>
struct HashFunc
{
	size_t operator()(const K& key)
	{
		return (size_t)key;
	}
};

// 特化
template<>
struct HashFunc<string>
{
	size_t operator()(const string& key)
	{
		size_t hash = 0;
		for (auto e : key)
		{
			hash *= 31;
			hash += e;
		}

		return hash;
	}
};
更多模板特化信息:

http://t.csdnimg.cn/IEY8T

板书

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

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

相关文章

app安全评估报告的常见留存措施(内附独家资料)

对用户账号、操作时间、操作类型、网络源地址和目标地址、网络源端口、客户端硬件特征等日志信息以及用户发布信息记录的留存措施 1**. 用户账号信息**&#xff1a;我们将用户账号信息安全存储&#xff0c;只有授权的人员能够访问。这些信息包括用户名、电子邮件地址等&#xf…

【C++ 面试 - 面向对象】每日 3 题(六)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/fYaBd &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏&…

VAuditDemo审计之二次注入漏洞

目录 VAuditDemo二次注入漏洞 搜索危险函数&#xff0c;用户可控点 regCheck.php messageSub.php message.php 漏洞调用链 漏洞错误利用过程 注册用户 xxxx, 发表payload留言 漏洞正确利用过程 注册用户 wwww\ 退出用户 wwww\\ 使用 wwww\ 登录 发表留言 替换dat…

《javaEE篇》--定时器

定时器概念 当我们不需要某个线程立刻执行&#xff0c;而是在指定时间点或指定时间段之后执行&#xff0c;假如我们要定期清理数据库里的一些信息时&#xff0c;如果每次都手动清理的话就太麻烦&#xff0c;所以就可以使用定时器。定时器就可以比作一个闹钟&#xff0c;可以让…

C++ 设计模式(6. 适配器模式)

适配器模式Adapter Pattern是一种结构型设计模式&#xff0c;它可以将一个类的接口转换成客户希望的另一个接口&#xff0c;主要目的是充当两个不同接口之间的桥梁&#xff0c;使得原本接口不兼容的类能够一起工作。基本结构 Target 是目标接口&#xff0c;Adaptee 是需要适配的…

微信小程序实例代码解读

以微信 小程序开发工具给的示例代码为例&#xff1a; 主页代码&#xff1a; index.wxml 这个文件是一个微信小程序页面的 WXML 结构,主要功能是展示一个快速开始教程的步骤和内容。 源代码&#xff1a; <!--index.wxml--> <view class"container">&l…

ZK-Rollups测评

1. 引言 Matter Labs团队和多个高校研究人员一起&#xff0c;发布2024年论文《Analyzing and Benchmarking ZK-Rollups》&#xff0c;开源代码见&#xff1a; https://github.com/StefanosChaliasos/zkrollup-benchmarking&#xff08;Python&#xff09; 其中&#xff1a; …

安装MySQL入门基础指令

一.安装MySQL(以5.7版本为例) 1.一路默认安装&#xff0c;截图供大家参考 修改自己window安装名字即可 2.配置环境变量 C:\Program Files\MySQL\MySQL Server 5.7\bin 写入系统环境变量即可在window窗口使用其服务了 3.登录MySQL服务 进入控制台输入命令 mysql -u root …

运维小技能:基于Windows系统和‌Linux系统,以tomcat为案例,讲解如何新增自启动服务。

文章目录 引言‌I Linux系统‌(以CentOS为例)基础知识:运行级别(run level)基于chkconfig 工具,设置服务启动类型。基于systemctl 新增系统服务II 基于Windows系统设置服务自启动的常规操作安装多个tomcat服务,并设置自启动。III 扩展制定定时任务优化停止Tomcat服务命令引…

ESP32Cam人工智能教学20

ESP32Cam人工智能教学20 ESP32Cam专用APP 这次我们专门为ESP32Cam量身定制一个手机APP。手机APP是客户端&#xff0c;利用Socket连接ESP32Cam&#xff0c;ESP32Cam成了服务器&#xff0c;实现Socket全双工的数据传输模式&#xff0c;还可以一边显示摄像头图像&#xff0c;一边…

【Canvas与诗词】北岛诗《献给遇罗克》节选(以太阳的名义...)

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>以太阳的名义</title><style type"text/css">…

基类没有虚析构,即使派生类使用智能指针也一定会内存泄漏

实验 定义一个基类和一个派生类 class Base { public:virtual ~Base() default; };class Derive :public Base { public:std::shared_ptr<int> sp{new int{0},[](int *p){delete p;std::cout << "删除器" << endl;},}; };main 函数执行如下代码…

作业08.21

服务器&#xff1a; #include <myhead.h>#define SER_PORT 6666 #define SER_IP "127.0.0.1"int find_client(int *client_arr, int len, int client) {for(int i0; i<len; i){if(client_arr[i] client){return i;}}return -1; }void remove_client(int *…

Mac 使用vscode 创建vue项目后修改文件提示:权限不足,以超级用户身份重试

项目场景&#xff1a; Mac 安装了全局 vue-cli 插件后&#xff0c;使用webpack 创建vue项目&#xff0c;打开项目&#xff0c;选择信任所有文件夹&#xff0c;然后正常编写代码&#xff0c;并对项目中的文件进行修改&#xff0c;点击保存的时候提示&#xff1a;保存“webpack.…

Vue3+Ts封装类似el-dialog的对话框组件

提供11个字段对dialog组件进行控制&#xff1a; modelValue: 对话框显示隐藏控制, width: 控制对话框的宽度, height&#xff1a;控制对话框的高度, top: 控制对话框个距离顶部的距离, title: 控制对话框的标题, appendToBody: 是否将对话框添加至body, closeOnClickModa…

GX Works2的使用方法

目录&#xff1a; 1、概述 2、硬件连接 3、录入与修改程序 1&#xff09;进入编辑按F2或点击“写入模式”图标 2&#xff09;修改部分元件 3&#xff09;注释 4&#xff09;改变显示触点数 4、软仿真与在线仿真 1&#xff09;软仿真 2&#xff09;在线仿真 5、P…

Linux源码阅读笔记-USB设备驱动架构

总线速度及主机控制器 USB系统架构 USB系统主机端提供为4个引脚的A型接口&#xff0c;USB外围设备通过4个引脚的B型接口和主机端连接。那4个引脚&#xff08;一条电压线VBUS、一条地线GND、一条正方向传输数据的D和一条反方向传输数据的D-线。&#xff09;USB主机和USB设备收发…

2024年翻译神器:探索四款好用的翻译工具!

因为有了一些翻译工具的存在&#xff0c;语言障碍已经渐渐不成问题。接下来就为大家推荐几款好用的翻译工具&#xff01; 福昕在线翻译 链接&#xff1a; https://fanyi.pdf365.cn/ 福昕在线翻译以其简洁的界面和强大的翻译能力&#xff0c;成为用户跨越语言障碍的首选。它…

独立站PrestaShop安装

独立站PrestaShop安装 独立站PrestaShop安装系统需求下载PrestaShop浏览器下载命令行下载 解压PrestaShop创建数据库移动PrestaShop源码到web目录composer安装依赖包nginx配置访问域名进入安装页面选择语言许可协议系统兼容性店铺信息Content of your store系统配置数据库店铺安…