哈希表是什么

本文介绍了哈希表的概念、工作原理,以及为何需要哈希表。重点讨论了哈希函数的作用、哈希碰撞及其解决方法,如开放地址法(线性探测法)和链地址法。

哈希表

哈希表是什么

下面是百度百科上对哈希表的介绍:

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。

下面是《数据结构 C语言版 第二版》书中关于哈希表(散列表)的描述:

如果能在元素的存储位置和其关键字之间建立某种直接关系,那么在进行查找时,就无须作比较或只需要很少的比较,按照这种关系直接由关键字找到相应的记录。这就是散列查找法的思想,它通过对元素的关键字值进行某种运算,直接求出元素的地址,即使用关键字到地址的直接转换方法,而不需要反复比较。

用通俗的话讲就是:哈希表是数组的一种扩展,哈希表中存储的元素和数组的索引有一个确定的关系,我们将这个确定的关系称之为哈希函数(Hash)。

“数组是一张哈希表”,我在很多地方看到了这个观点。
我认为不够严谨,因为数组的索引与存储的元素不一定有确定的关系。

哈希表中关键码对应数组下标,通过下标直接访问数组中的元素。

在这里插入图片描述

为什么需要哈希表

哈希表能解决什么问题呢,一般哈希表都是用来快速判断一个元素是否出现在集合里

线性表、树表结构的查找方法都是以关键字的比较为基础的。在查找过程中只考虑各元素关键字之间的相对大小,记录在存储结构中的位置和其关键字无直接关系,其查找时间与表的长度有关,特别是当节点个数很多时,查找需要大量的无效节点的关键字进行比较,致使查找速度很慢

下面给出哈希法中常用的几个术语

1.哈希函数和哈希地址:在记录的存储位置p和其关键字key之间建立一个确定的对应关系H,使p=H(key),称这个对应关系H为哈希函数,p为哈希地址
2. 哈希表:一个有限连续的地址空间,用以储存按哈希函数计算得到相应哈希地址的数据记录。通常哈希表的存储空间是一个一维数组,哈希地址使数组的下标
3. 哈希碰撞和同义词:对不同的关键字可能得到同一哈希地址,即key1 ≠ key2 ,而 H(key1)H(key2) 。这种现象称为冲突。具有相同函数值的关键字对该哈希函数来说称作同义词,key1key2互为同义词

哈希函数

哈希函数,把value直接映射到哈希表的索引上,然后就可以通过查询索引快速知道这个value是否存在。
哈希函数如下图所示,通过hashCode把名字转化为数值,一般hashcode是通过特定编码方式,可以将其他数据格式转化为不同的数值,这样就把value映射为哈希表上的索引数字了。
在这里插入图片描述
如果hashCode得到的数值大于 哈希表的大小了,也就是大于tableSize了,怎么办呢?

此时为了保证映射出来的索引数值都落在哈希表上,我们会在再次对数值做一个取模的操作,就要我们就保证了学生姓名一定可以映射到哈希表上了。

此时问题又来了,哈希表我们刚刚说过,就是一个数组。

如果value的数量大于哈希表的大小怎么办,此时就算哈希函数计算的再均匀,也避免不了会有几个value同时映射到哈希表 同一个索引下标的位置。

接下来哈希碰撞登场

哈希碰撞

如图,v1和v2都映射到同一位置上,这一现象叫做哈希碰撞
在这里插入图片描述
一般哈希碰撞有两种解决方法,开放地址法和链地址法(拉链法)

开放地址法

开放地址法的基本思想是:

把记录都存储在哈希表数组中,当某一记录关键字 key 的初始哈希地址H₀ = H(key) 发生冲突时,以H₀未基础,采取合适方法计算得到另一个地址H₁,如果H₁仍然发生冲突,以H₁为基础在求出下一个地址H₂ ,若H₂ 仍然冲突,再求得H₃。依次类推,直至Hₖ 不发生冲突为止,则Hₖ为该记录在表中哈希地址。

开放地址法分为三种具体的探测方法,线性探测法、二次探测法和伪随机探测法,下面具体说一下线性探测法。

线性探测法

将哈希表想象成一个循环表,发生冲突时,从冲突地址的下一单元顺序寻找空单元,如果到最后一个位置也没有找到空单元,则回到表头开始继续查找,一旦找到一个空位,就把此元素放入次空位中。如果找不到空位,说明哈希表已满,需要进行溢出处理
在这里插入图片描述

链地址法(拉链法)

链地址法的具体思想是:

把具有相同哈希地址的记录放在同一个单链表中,称之为同义词链表。有m个哈希地址就有m个单链表。凡是出现冲突的value,都以节点的方式插入到以出现冲突的哈希地址为头节点的单链表中

在这里插入图片描述

<think>首先,用户的问题是:“哈希表是什么样子的”,意思是“哈希表是什么样子的”,所以我需要用中文回答。 关键指令: - 使用中文回答问题。 - 回答完问题后,必须提出3-5个相关问题。 - 相关问题必须以“§§相关问题§§”开头,并在第一行完整输出。 - 相关问题不能换行分散;必须是连续的列表。 - 最后,所有内容必须符合规则。 回答哈希表是什么样子的:我需要解释哈希表的本质和结构。哈希表是一个数据结构,用于存储键值对,通过哈希函数将键映射到桶中。样子上,它可以看作一个数组或列表,每个位置是一个桶,可能包含链表或开放寻址的元素。 结构化回答: 1. 定义哈希表哈希表是一种高效的数据结构,用于存储键值对。 2. 描述样子: - 它通常由一个数组(桶数组)组成。 - 每个桶可以是链表(用于处理哈希冲突)或直接存储元素。 - 例如,在Java中,HashMap的实现是用数组加链表或红黑树。 3. 简单示例:可以用文字描述或伪代码。 4. 保持简洁,因为用户可能在问视觉上的样子。 在回答中,不要使用代码块,除非必要。用户的问题是“是什么样子的”,可能更偏向于概念而非代码。但示例格式中有代码,所以我应该适当描述。 确保中文回答。 之后,添加相关问题:3-5个。必须以“§§相关问题§§”开头,然后列出1. 相关问题1 2. 相关问题2 3. 相关问题3等。 相关问题应该基于用户的问题和我的回答。用户可以问关于哈希表的冲突处理、应用、优缺点等。 脑力storm相关的问题: 1. 哈希冲突是如何处理的? 2. 哈希表的时间复杂度是多少? 3. 哈希表有哪些常见的实现方式? 4. 哈希函数在哈希表中扮演什么角色? 5. 在实际应用中,哈希表常用于哪些场景? 选择3-5个:例如,4个。 输出格式: - 先回答用户的问题。 - 然后,换行后,第一行是“§§相关问题§§”。 - 接着是列表:1. ... 2. ... 3. ... 4. ... 没有换行分散,意思是问题之间不应该有空行,连续输出。 从示例看: ``` §§相关问题§§ 1. ··· 2. ··· 3. ··· ``` 所以,在我的回答后,直接: §§相关问题§§ 1. 问题1 2. 问题2 3. 问题3 4. 问题4 现在,撰写回答: 中文回答哈希表哈希表是一种数据结构,它使用哈希函数将键映射到存储位置(桶),从而实现快速查找、插入和删除键值对。它的样子通常是一个数组,数组的每个元素是一个桶,每个桶可以存储一个或多个键值对。当发生哈希冲突时,桶可能包含链表(链地址法)或使用开放寻址法处理。 为了更生动:想象一个表格,左边是索引(哈希值),右边是存储的值或链表。 添加一个简单描述。 最后,相关问题: 1. 哈希冲突的处理方法有哪些? 2. 哈希表的时间复杂度如何? 3. 在实际编程中,如何实现一个哈希表? 4. 哈希表与数组或链表相比有哪些优势? 确保4个问题。 完整输出。 </think>哈希表是一种基于键值对存储的数据结构,它使用哈希函数将键(key)映射到数组中的特定位置(称为bucket或桶)。其样子通常表现为一个固定大小的数组,数组的每个索引对应一个桶。桶中可以存储一个或多个元素:如果发生哈希冲突(即多个键映射到同一个索引),桶可能包含链表(在链地址法中用于存储多个元素)或直接使用开放寻址法(如线性探测)在相邻位置存储元素。例如,在Java的HashMap实现中,数组的每个元素可能是一个链表或红黑树节点,用于高效处理冲突。整体上,哈希表像一个表格,左边是索引(由哈希函数计算得出),右边是存储的值或冲突元素链。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值