哈希表(hash table)基础概念

哈希是什么

引入:我们在学习数组的时候,使用数组元素的下标值即可访问到该元素,所花费的时间是O(1),与数组元素的个数n没有关系,这就是哈希方法的核心思想。

哈希方法:以关键值K为自变量,通过一定的函数关系h(K)(哈希函数)计算出对应的函数值,把这个值解释为结点的存储地址,将结点的关键码(key)和属性数据(value)一起存入此存储单元中。检索时,用同样的函数计算出地址,找到对应的数据。

哈希表:按哈希存储方式构造的存储结构称为哈希表(hash table)

举例:已知线性表关键码值集合为S={and, begin, do, else, for,golang},假设哈希函数是关键码K的第一个字母在字母表中的序号,哪么可以建立如下的哈希表:

当然这个例子特别简单,细心的同学很快就发现了二个问题:

  1. 如果S中有类似于and,apple这样的关键码,哪么这个表还怎么存放,在1的位置存放and还是apple呢?(这种现象称为冲突
  2. 分配的空间大小比实际所需的要大一点(一般情况下,哈希表的空间(H)比结点的集合(M)大,这样虽然浪费了空间,但是换来了检索效率,称α=M/H为哈希表的负载因子

其实这就是接下来要谈到的哈希函数的选择和冲突解决策略。

哈希函数

哈希方法的核心就是哈希函数的选择,理想的哈希函数应该使得结点“分布均匀”,且冲突少

为了简单起见,以下的哈希函数我们假设关键值都是整数(如果不是整数,哪也有特定的方法可以把它转换为整数,毕竟在计算机世界里,任何东西都是01组成的串)

除余法:

关键值码k除以M(往往取哈希表的长度),并取余数作为哈希地址。

乘余取整法

先让关键码k乘上一个常数A(0<A<1),提取乘积的小数部分。然后,再用整数n乘以这个值,对结果向下取整,将其作为哈希的地址。

有许多种哈希函数可以选择,每种都有其适用的场景,但是作为软件开发工程师,我们只要理解它的思想就可以,至于什么场景选择什么哈希函数,哪大概率是数学家应该研究的问题。

优秀的哈希函数可以尽可能的避免产生冲突,但是冲突的产生是不可避免地,这就是接下来要谈到的冲突解决策略

冲突解决策略

冲突解决技术可以分为两类,拉链法和开地址法,这两种方法的不同之处在于,拉链法把发生冲突的关键码存储在哈希表主表之外,而开地址法把发生冲突的关键码存储在表中另一个槽内。

拉链法

拉链法的一种简单形式是把哈希表中的每一个槽定义为一个链表的表头,哈希到一个特定槽的所有记录都放到这个槽的链表中。

假设S={and, apple, begin, do, dog, else, for, go, golang},哈希函数还是关键码K的第一个字母在字母表中的序号。哪么可以建立如下的哈希表:

开地址法

开地址法把所有记录直接存储在哈希表中。每个记录关键码K有一个由哈希函数计算出来的基位置,即h(k)。如果要插入一个关键码k,而另一个记录的关键码已经占据了k的基位置(发生冲突)则把k存储在表中的其他地址内,至于其他地址怎么选择,有多种算法,我们以顺序探测法为例。

已知一组关键码为{26,36,41,38,44,15,68,12,06,51,25},哈希表长度L=15,用线性探查法解决冲突构造的哈希表的过程如下:

利用除余数作为哈希函数,假设选择M=13,则散列函数为:h(k)=k%13,按顺序插入各个结点:

h(26)=0, h(36)=10,h(41)=2, h(38)=12, h(44)=5,

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
26 25 41 44 36 38

h(15)=0,发生碰撞,因此需要进行探查,按照顺序探测法,显然3为开放的空闲地址,因此可以将其放在3单元。

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
26 25 41 15 44 36 38

68和12也类似,最后的哈希表如下所示:

1 2 3 4 5 6 7 8 9 10 11 12 13 14
26 25 41 15 68 44 6 36 38 12 51

小结

本文简述了哈希表的基本概念和思想,作为软件工程师,掌握这些知识足够我们从事工程开发了,至于一些偏数学方面的知识,比如散列方法的效率分析,以及相关的一些优化,本文就不再讲述。

参考资料:《数据结构与算法》张铭 编著

原文地址:https://www.cnblogs.com/yahuian/p/11575672.html

时间: 2024-11-13 10:39:42

哈希表(hash table)基础概念的相关文章

哈希表(Hash table)(1)

哈希表(Hash table)经常被用来做字典(dictionary),或称符号表(symbol-table) 直接存取表(Direct-access table): ? 直接存取表(Direct-access table)的基本思想是:如果key的范围为0~m-1而且所有key都不相同, 那么可以设计一个数组T[0..m-1],让T[k]存放key为k的元素, 否则为空(NIL) ? 显然, 所有操作都是O(1)的 ? 问题:key的范围可能很大! 64位整数有18,446,744,073,7

PHP关联数组与哈希表(hash table) 不指定

PHP中有一种数据类型非常重要,它就是关联数组,又称为哈希表(hash table),是一种非常好用的数据结构. 在程序中,我们可能会遇到需要消重的问题,举一个最简单的模型: 有一份用户名列表,存储了 10000 个用户名,没有重复项: 还有一份黑名单列表,存储了 2000 个用户名,格式与用户名列表相同: 现在需要从用户名列表中删除处在黑名单里的用户名,要求用尽量快的时间处理. 这个问题是一个小规模的处理量,如果实际一点,2 个表都可能很大,比如有 2 亿条记录. 我最开始想到的方法,就是做一

哈希表 hash table

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构.也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度.这个映射函数叫做散列函数,存放记录的数组叫做散列表. 给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数. 首先问题规模确定,例如5台服务器怎么把数据散落在5台上面呢,就用到了hash算法

什么叫哈希表(Hash Table)

散列表(也叫哈希表),是根据关键码值直接进行访问的数据结构,也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度.这个映射函数叫做散列函数,存放记录的数组叫做散列表. - 数据结构中,有个时间算法复杂度O(n)的概念来衡量某种算法在时间效率上的优劣.哈希表的理想算法复杂度为O(1),也就是说利用哈希表查找某个值,系统所使用的时间在理想情况下为定值,这就是它的优势.那么哈希表是如何做到这一点的呢? - 我们定义一个很大的有序数组,想要得到位于该数组第n个位置的值,它的算法复杂度

[BS]散列表 哈希表 Hash table

<第五章> 散 列 散列表的实现常常叫做散列(hashing).散列是一种用于以常数平均时间执行插入.删除和查找的技术. 关于散列有一个很重要的概念:散列函数.散列函数是散列的关键处之一,散列函数又是基于映射机制的一种对应关系(一般是多对一的关系). 这章可以分为5个部分:一般想法,散列函数,分离链接法,开放定址法(可分为线性探测.平方探测.双散列).再散列.可扩散列. 本文只写到前四节.即:一般想法,散列函数,分离链接法,开放定址法(可分为线性探测.平方探测.双散列)() 第五章第一节:一般

哈希表Hash

大家都学过数据结构: 内存里面为了更好的管理对象,通常采用链表或者数据以及Hash表来存储数据. 数据存储 一下是数据存储到计算机的两种模式 线性的存储:数组---寻址方便,更新不好(连续的) 链式的存储: 链表----寻址不方便,更新方便.(不连续的) 为了提高检索的速度,我们可以采取Hash机制,key采取数据存储,方便寻址,其次我们可以利用链表方便更新数据的具体的值. 哈希表Hash,布布扣,bubuko.com

(四)Redis哈希表Hash操作

Hash的全部操作如下: hset key field value # 将哈希表key中的字段field的值设为value hget key field # 返回哈希表key中的字段field的值value hmset key field1 value1 field2 value2 ... # 将多个field-value对设置到哈希表key中 hmget key field1 field2 ... # 返回哈希表key中字段field1,field2,...的值 hgetall key # 返

哈希表Hash:概念与基本操作

什么是Hash Hash就像是一个桶排,那只不过是把各个元素的数值当做下标进行存储.其最常用的用途就是用来判重.但是,如何对字符串进行判重,不可能一个一个往前超,若n上万则显然不可行.我们可以选择进行Hash,将每一个字符串或者大数字进行一定的操作即可进行. 对大整数类型进行Hash 取模法 对于每一个大整数进行取模,即除以一个大质数(例如107,10007,1000007,1-奇数个0-7),这样就作为数组的下标进行存储了. 为什么要对一个大整数取模 emmmmmm......经众多数学家证明

线性表的相关基础概念

一个线性表是由n个数据元素构成的有限序列,其特点是数据元素之间存在着线性关系.在计算机中表示这种关系的两种不同存储结构是顺序存储结构和链式存储结构. 1.顺序表 顺序表是在内存中用一组地址连续的存储单元依次存储线性表的数据元素,借助数组来实现.顺序表中数据元素的逻辑关系通过其"存储位置相邻"来表示. 对于顺序表,主要有初始化.建立.销毁.插入.删除.按值查找.等基本操作.插入和删除操作约需移动一半的元素,时间复杂度为O(n). 2.链表 除了常用的单链表外,还有循环链表.双向链表.双向

数据结构基础-Hash Table详解(转)

理解Hash 哈希表(hash table)是从一个集合A到另一个集合B的映射(mapping). 映射是一种对应关系,而且集合A的某个元素只能对应集合B中的一个元素.但反过来,集合B中的一个元素可能对应多个集合A中的元素.如果B中的元素只能对应A中的一个元素,这样的映射被称为一一映射.这样的对应关系在现实生活中很常见,比如: A  -> B 人 -> 身份证号 日期 -> 星座 上面两个映射中,人 -> 身份证号是一一映射的关系.在哈希表中,上述对应过程称为hashing.A中元