散列查找

when ? what ? why ? how ?

why

为什么要用散列查找?

what

什么是散列查找?

解决冲突有哪些方法?

how

如何评估查找?

散列函数如何设计?


为什么要用散列查找?

顺序查找 时间复杂度 O(N)

二分查找(前提有序) 时间复杂度 O(logN)

二叉搜索树 时间复杂度 O(h),h 是树高,最好情况 h = logN,最差 h = N 。

二叉平衡树 时间复杂度 O(logN)

如何数据量很大时怎么办,10 亿,100 亿 ?

顺序查找全部遍历不可能 ,二分查找要求有序太难了,2 的 30 次方等于10 亿多,那么二叉搜索树、二叉平衡树最好情况下树高 30,比 30 次也有点多。

散列查找:通过散列函数的计算求出关键字的位置。 这样就有很快的查找效率。时间复杂度几乎是常量 O(1)。


什么是散列查找?

散列 (Hashing) 是一种重要的查找方法。它的基本思想是:以数据对象的关键字 key 为自变量,通过一个确定的函数关系 h,计算出对应的函数值 h(key) ,把这个值解释为数据对象的存储地址(可能不同的关键字会映射到同一个散列地址上会有冲突,需要解决),并按此存放,即“存储位置= h(key)”。

散列表(Hash Table)也称为哈希表。

散列查找的两项基本工作:

  1. 计算位置:构造散列函数确定关键字存储位置
  2. 解决冲突:应用某种策略解决多个关键词位置

散列函数如何设计?

散列函数的设计需要考虑下列两个因素:

  1. 计算简单,以便提高转换速度
  2. 关键词对应的地址空间分布均匀,以尽量减少冲突

数字关键词的散列函数构造

1.直接定址法

如统计出生年份所对应的人数

h(key) = key -1990

取关键词的某个线性函数值为散列地址

h(key) = a * key + b ( a 、 b 为常数)

直接定址法现实中不常用。

2.除留余数法

h (key) = key mod p

如 h(key) = key % 13

TableSize = n / α, n 是关键词集合大小,α 是允许最大装填因子

一般 p 取素数,p <= TableSize

现实应用中比较常见的方法。

3.数字分析法

如果数字关键词的位数比较多,取比较随机的的位作为散列地址。

4.折叠法

把关键词分割成位数相同的几个部分,然后叠加

5.平方取中法

字符关键词的散列函数构造

1.一个简单的散列函数————ASCII码加和法

对字符关键词 key 定义散列函数如下:

h(key) = (∑key[i]) mod TableSize

函数简单,均匀性比较差,冲突比较严重。

2.简单的改进————前 3 个字符移位法

h(key) = (key[0] * 27^2 + key[1] * 27 + key[2] ) mod TableSize

3.好的散列函数————移位法

涉及关键词所有 n 个字符,并且分布得很好:


解决冲突有哪些方法?

换个位置: 开放地址法

同一位置的冲突对象组织在一起: 链地址法

开放定址法

若发生了第 i 次冲突,试探的下一个地址将增加 di,基本公式是:

1.线性探测

如上图:出现了聚集现象,为了优化出现了下面几种

2.平方探测

平方探测在一定程度上减轻了聚集现象

3.双散列

探测序列应该保证所有的散列存储单元都应该能够被探测到。

p < TableSize, p 、 TableSize 都是素数

4.再散列

当散列元素太多(即装填因子 α 太大),查找效率会下降:实用最大装填因子一般去 0.5 <= α <= 0.85

当装填因子过大时,解决的方法是加倍扩大散列表。

分离链接法

将相应位置上冲突的所有关键词存储在同一个单链表中。

h(key) = key mod 11


散列表的性能分析

平均查重长度(ASL)用来度量散列表查找效率:成功、不成功

影响产生冲突的三个因素:

  1. 散列函数是否均匀
  2. 处理冲突的方法
  3. 散列表的装填因子 α(分离链接法的装填因子是所有地址链表的平均长度)

总结

参考

数据结构 陈越 何钦铭

选择合适的 h(key),散列表的查找效率期望是常数 O(1),它几乎与关键字的空间大小 n 无关!也适合于关键字直接比较计算量大的问题

散列查找是以较小的 α 为前提。因此,散列方法是一个以空间换时间

散列方法的存储对关键字是随机的,不便于顺序查找关键字,也不适合于范围查找,或最大值最小值查找。

开放定址法

  1. 散列表是一个数组,存储效率高,随机查找。
  2. 散列表有聚集现象

分离链接法

  1. 散列表都是顺序存储和链式存储的结合,链表部分的存储效率和查找效率都比较低。
  2. 太小的 α 可能导致空间浪费,大的 α 又将付出更多的时间代价。不均匀的链表长度导致时间效率的严重下降。

有什么问题欢迎指出,十分感谢!

posted @ 2018-07-14 15:24  罗贱人  阅读(999)  评论(0编辑  收藏  举报