Hash函数与取模运算
2019-04-13 17:34发布
生成海报
1.
hash
函数
哈希表也称散列表
,
是一种数据结构
,
它可以提供快速的插入操作和查找操作
,
不论有多少数据项
,
插入与删除只需要接近常量的时间
:O(1)
时间级
。
但哈希表也有缺点
,
它是基于数组的
,
数组一旦被创建
,
就难以扩展
。
某些哈希表被填满时
,
性能急剧下降
。,
所以程序员必须清楚表中要存储多少数据
。
哈希表操作的平均时间是基于统计特性而不是随机输入的期望值
。
哈希表的重要特性就是哈希函数
。
我们用一个将大数
(
或解释为数的字符串
)
映射成一个较小的
,
更容易管理的数的函数来达到这个目的
。
将一个项映射成一个较小的下标的函数称为哈希函数
。
需要哈希函数
,
是因为哈希表是基于数组的
,
而且关键字值的范围通常比数组容量大
。,
关键字值通过哈希函数映射为数组的下标
。
哈希函数一般是通过取模运算来实现(
key = tag % constant)
,
这就是一个简单的哈希函数
。
但也带来了不可避免的麻烦
:
两个或更多的不同项可能被散列到同一个位置
,
引起冲突
。
2.
减少冲突
2.1.
开放地址法
开放地址法
:
让指定的数组大小两倍于需要存储的数据量。因此,可能一半的单元是空的。当冲突发生时,一个方法是通过系统的方法找到数组的一个空位,并把这个数据填入,而不再用哈希函数得到的数组下标。
在开放地址法中如果数据不能直接放在由哈希函数中,就得寻找空白位置,其中简单的三种探索方法。
线性探索法
,
二次探索法
,
再哈希法
。
2.2.
链地址法
链地址法
:
创建一个存放数据链表的数组,数组内不直接存储数据。这样,当发生冲突的时候,新的数据项直接接到这个数组下标所指的链表中。
在链地址法中
,
数据项的关键字值还是映射到数组下标
,
而数据本身保存在每个单
元的链表中
。
当然如果链表中有许多项
,
存取时间变长
,
找到初始单元的时间为
O(1)
,
而搜索链表的时间与链表中的数据项数目
M
成正比
,
为
O(M)
。
因此并不希望链表太满
。
3.
经验
专家发现以下哈希函数形式很好
:
key = (tag % constant )
其中
constant
为质数
,
并且小于哈希表容量
。这样哈希值就分布的比较均匀,效率就不会受影响。
3.
开源项目哈希实现
hashtable.h
hashtable.c
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮