哈希查找
我们之前学过的几种查找方法:
- 顺序查找
- 二分查找(静态查找)
- 二叉搜索树 h为二叉查找树的高度
- 平衡二叉树
还有没有更快的查找方法呢?
我们先看下面的例子:
在登陆QQ的时候,QQ服务器是如何核对你的身份的?面对庞大的用户群,如何快速找到用户信息?
如果用二分法查找:
- 十亿( )有效用户,所以用二分法查找30次。
- 十亿( ) ,也就是需要1T的连续空间。
- 按有效QQ号大小有序存储:在连续存储空间中,插入和删除一个新的QQ号码将需要移动大量数据。
如何快速搜索到需要的关键词呢?如果关键词不方便比较怎么办?
我们看看查找的本质:已知对象找位置。
- 有序安排对象:全序、半序
- 直接“算出”对象位置:散列
于是我们引进哈希查找法。
哈希查找法的两项基本工作:
- 计算位置:构造哈希函数确定关键词存储位置;
- 解决冲突:应用某种策略解决多个关键词位置相同的问题。
时间复杂度几乎是常量:O(1),即查找时间与问题规模无关。
散列的基本思想
- 以关键字 为自变量,通过一个确定的函数 (散列函数),计算出对应的函数值 ,作为数据对象的存储地址。
- 可能不同的关键字会映射到同一个散列地址上,即 (当 )
,称为“冲突(Collision)”。——需要某种冲突解决策略
例一
有n = 11个数据对象的集合{ 18,23,11,20,2,7,27,30,42,15,34 }。
哈希表的大小用TableSize = 17,选取哈希函数h如下:
(取余)
因为18 % 17 = 1,所以h(18) = 1
因为23 % 17 = 6,所以h(23) = 6
因为11 % 17 = 11,所以h(11) = 11
......
得到:
地址 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
关键词 | 34 | 18 | 2 | 20 | 23 | 7 | 42 | 27 | 11 | 30 | 15 |
假设新插入35,h(35) = 1,该位置已有对象,冲突!(在后面我们将讨论怎么解决冲突)
查找:
- key = 22,h(22) = 5,该地址空,不在表中
- key = 30,h(30) = 13,该地址存放是30,故而找到了。
补充:
装填因子(Loading Factor):设散列表空间大小为m,填入表中元素个数是n,则称 为散列表的装填因子。
例二
将acos、define、float、exp、char、atan、ceil、floor,顺次存入一张散列表中。
散列表设计为一个二维数组Table[26][2],2列分别代表2个槽。
设计散列函数 h(key) = key[ 0 ] - ‘a’
如果没有溢出,
end