1. 介绍
散列表又名散列表,是实现字典操作的一种数据格式,其有增删查改操作,在最坏情况下,其查找时间为 θ(n) , 平均时间下为 O(1)
1.1 需要理解的几个概念
- 全域U:关键字 K 所在集合
- 槽:关键字k散列到散列表的位置
- 散列方法h(k): 用于计算关键字k所在散列表中槽的位置
- 冲突:同一槽中可能会被散列多个关键字,称之为冲突
- 简单均匀散列:关键字等可能性的散列到m个槽中的任何一个,其与其他元素散列到什么位置无关
- 装载因子
a
:一个槽位,平均存储元素数, 在简单均匀散列假设下,
a=n/m
1.2 什么是好的散列函数
- 尽可能近似简单均匀散列
- 近似key散列到同一槽中的可能性最小化
- 散列方法应不受关键字分布的影响
2. 散列冲突的两种解决方法
2.1 链接法解决散列冲突
将散列到同一槽中的所有元素放入一个链表中
2.1.1 链接表性能分析
- 简单均匀散列假设下,一次不成功查找的时间复杂度为 θ(1+a)
- 简单均匀散列假设下,一次成功查找的时间复杂度为 θ(1+a)
注:
1)最坏情况为,所有元素都被散列到同一槽中,此时查找时间为 θ(n)
2)当槽数 m 与 元素数 n 成正比时,有 n=O(m) , 则 a=n/m=O(1)
2.2 开放寻址表解决散列冲突
插入元素时,连续的探查(probe)散列表,直到探查一个空槽, 并插入元素。
注:
1) 槽位可能被全部占满
2) 装载因子 a<=1
2.2.1 常用的探查方法
- 线性探查
- 二次探查
- 双重探查
2.2.2开放寻址表性能分析
时间花销主要在探查次数上,探查次数 = 探查发生冲突的次数 + 1
设 随机变量 X 为探查发生冲突的次数,
定义事件 Ai (i=1,2,…)为第i次发生了冲突的探查
在简单均匀散列假设下, 期望的探查次数 ≤11−a
证明:{X≥i}=A1⋂A2⋂...⋂Ai−1
故有
Pr{X≥i}=Pr{A1⋂A2⋂...⋂Ai−1}=nm⋅n−1m−1⋅n−2m−2⋅n−i+2m−i+2≤(nm)i−1=ai−1
则E[X]=∑i=1∞Pr{X≥i}≤∑i=1∞ai−1=∑i=0∞ai=11−a在简单均匀散列假设下, 向一个装载因子为 a 的开放寻址表中插入一个元素,探查次数
≤11−a - 在简单均匀散列假设下, 一次成功查找的探查期望数 ≤1aln11−a
注:a 越大,即散列表越密集, 探查次数越多;a越小,即散列表越稀疏,探查次数越小,结论为 表越稀疏,效率越高。
3. 常用散列方法
- 除法散列 h(k) = k mod m
- 乘法散列
- 全域散列
- 完全散列
下一章我们会详细讲解这几种散列方法