哈希表
哈希表定义
哈希表是又称散列表,一种以 "key-value"
形式存储数据的数据结构。所谓以 "key-value"
形式存储数据,是指任意的key
都唯一对应到内存中的某个位置。只需要输入查找的值 key
,就可以快速地找到其对应的 value
。可以把哈希表理解为一种高级的数组,这种数组的下标可以是很大的整数,浮点数,字符串甚至结构体。
哈希函数
要让 key
对应到内存中的位置,就要为 key
计算索引,也就是计算这个数据应该放到哪里。这个根据 key
计算索引的函数就叫做哈希函数,也称散列函数。
举个例子,比如 key
是一个人的身份证号码,哈希函数就可以是号码的后四位,当然也可以是号码的前四位。生活中常用的**“手机尾号”**也是一种哈希函数。
应用中,key
可能是更复杂的东西,比如浮点数、字符串、结构体等,这时候就要根据具体情况设计合适的哈希函数。哈希函数应当易于计算,并且尽量使计算出来的索引均匀分布。
在ACM
中,最常见的情况是key
为整数的时候,当key
的范围比较小的时候,就可以直接把key
作为数组下标,但当key
的范围比较大的时候(),就需要用到哈希表了,一般我们取一个大质数M
,将key
模M
之后作为索引,也就是作为h哈希函数。
还有一种情况也就是之后要介绍的字符串哈希在中特别常见,我们一般不直接把字符串作为,而是先计算出字符串的哈希值,再把其哈希值作为插入到哈希表中。
能为 计算索引之后,我们就可以知道每个 应该放在哪里了。假设我们用数组 存放数据,哈希函数是 ,那键值对 就应该放在 上。不论 是什么类型,范围有多大,
如何处理冲突
如果对于任意的 ,哈希函数计算出来的索引都不相同,那只用根据索引把 放到对应的位置就行了。但实际上,常常会出现两个不同的,他们用哈希函数计算出来的索引是相同的。这时候就需要一些方法来处理冲突。在
拉链法
拉链法也称开散列法()。
拉链法是在每个存放数据的地方开一个链表,如果有多个 $key $索引到同一个地方,只用把他们都放到那个位置的链表里就行了。查询的时候需要把对应位置的链表整个扫一遍,对其中的每个数据比较其 $key $与查询的 $key [1,M)$,哈希表的大小为 ,那么一次插入/查询需要进行期望次比较。
另外还有闭散列法处理冲突(基本不用)。
代码实现
拉链法
下面我白嫖的wzy学长封装的: