数据结构-散列(1)
一、散列表(Hash table)
1、散列表用来表示集合和字典,通过散列函数建立从元素关键码集合到散列表地址集合的一个映射,搜索时可以直接到达或者逼近具有对应关键码的元素的实际存放地址;
2、散列函数是压缩映像函数,关键码集合比散列表地址集合大得多,所以经过散列函数的计算会把不同的关键码映射到同一个散列地址上,散列地址相同的不同关键码互为同义词;
3、构造散列函数的要求:
(1)、定义域必须包括需要存储的全部关键码,若散列表允许有m个地址则其值域必须在0到m-1之间;
(2)、散列函数计算出来的地址能均匀分布在整个地址空间中;
(3)、尽量简单,能在较短时间内计算出结果;
二、散列方法
1、除留余数法:
思想:设散列表中允许的地址数为m,取一个不大于m但最接近于或等于m的质数p(p不接近2的幂)作为除数,利用公式将关键码转换为散列地址;
转换公式:
hash(key) = key%p (p<=m && p为质数 && p不接近2的幂次);
注意:若选p为2的幂次,则散列函数hash(key)计算出来的地址就是key的低n位二进位数字;若key为十进制数且取p为10的幂次,则散列函数hash(key)计算出来的地址就是key的低n位数字;总而言之,在key为R进制数的条件下,避免选取p为R的幂次,否则会因为地址分布太集中而导致冲突增多;
2、数字分析法:
思想:设有n个d位数,每个数的每一位可能有r种不同的符号;对这n个数整体而言(可看做n行d列的位矩阵),r种不同符号在各位上出现的几率不尽相同,可能在某些位上每种符号出现的机会均等,可能在某些位上只有某几种符号经常出现;可根据散列表的大小选取其中各种符号分布均匀的若干位作为散列地址;
适用范围:必须事先知道关键码并明确所有关键码每一位数值的分布情况,换一个关键码集合就必须重新计算;
计算各位数字中符号分布的均匀度的公式:
yk = (a1k-n/r)2+(a2k-n/r)2+...+(ark-n/r)2
其中,aik表示第i个符号在第k位上出现的次数(注意不是次幂!!!),n/r表示各种符号在n个数中均匀出现的期望值,计算结果越小表明在该位上各种符号分布得越均匀;
例子:
9 4 2 1 4 8
9 4 1 2 6 9
9 4 0 5 2 7
9 4 1 6 3 0
9 4 1 8 0 5
9 4 1 5 5 8
9 4 2 0 4 7
9 4 0 0 0 1
——————————
位标记: 1 2 3 4 5 6
一共有8个数,每个数6位,所以n=8且d=6;容易验证不同的符号个数r=10;
1位:仅有9出现且出现8次,所以y1=(8-8/10)2+(0-8/10)2*9=56.60;
2位:仅有4出现且出现8次,所以y2=(8-8/10)2+(0-8/10)2*9=56.60;
3位:2出现2次,1出现4次,0出现2次,有7种符号没有出现,所以y3=(2-8/10)2+(4-8/10)2+(2-8/10)2+(0-8/10)2*7=16.60;
...... 依次类推,计算可得y4 =y5=y6=5.60;
根据上述计算结果,若散列表地址范围有3位数字,则取各关键码的第4、5、6位作为记录的散列地址;
-------------------------------------------------------------------------------------------------------------------------------------------------------
夜深了,平方取中法、折叠法以及处理冲突的闭散列方法将在后续的散列笔记中介绍~