哈希搜索(闭散列,开散列)
为什么提出哈希?
顺序搜索和二叉树搜索中,元素存储位置和元素关键码之间没有联系。因此在查找一个数据时,必须经过关键码的多次比较,搜索效率取决于比较次数。而一个理想的搜索是不经过比较,直接拿出数据,建立关键码和存储位置的关系。
哈希冲突的产生与解决
不同的关键码通过相同的哈希函数计算出相同的地址,产生冲突。
因此在设计哈希函数时,要尽量避免冲突,而冲突是不可完全避免的。
常用hash函数:
- 直接定址法, hash = Key*A + B,需要事先知道关键字分布。
- 除留余数法, hash = Key % p,p是最接近关键字个数的最大质数。
- 平方取中法,适合位数不大,不知道关键字分布的情况。
- 折叠法,适合位数较大。
而处理hash冲突有两种解决方案,闭散列和开散列。
闭散列
当hash表中未存满时,就可将数据存入下一个空位。
寻找空位的两种方式:
线性探测
从冲突的位置开始,逐次+1向后寻找空位置,直至遍历一遍未找到空位置。
缺陷:一个冲突引起后面的关键码都后移冲突,形成堆积。
二次探测
从冲突位置开始,每次加 i^2 个位置,i是冲突的第几次。
负载因子α:元素个数 / 散列表长度,a超过0.8导致冲突可能性大
实现
具体实现需要置三个状态位
https://github.com/zzaiyuyu/OpenHashing
开散列
首先对关键码集合用散列函数计算散列地址,具有相同地址的关键码归于同一子集合,每一个子集合称为一个桶,各个桶中的元素通过一个单链表链接起来,各链表的头节点存储在哈希表中。
插入:相同的哈希地址插入到链表头结点
删除:在哈希桶中不断判断值是否相等进行删除
查找:找到hash地址对应的桶遍历