【数据结构】哈希表的概念及应用
前言
哈希表是一种根据关键码去寻找值的数据映射结构,该结构通过把关键码映射的位置去寻找存放值的地址,在计算机操作系统中,通过任务管理器能查看到系统为每个运行的程序(进程),分配的进程识别号(PID),假设当前系统中有7个进程处在运行状态,且它们对应的进程编号(PID)构成了一个{7,8,30,11,18,9,14}值的集合,请采用哈希函数:H(key)=(key*3) % 7,处理冲突采用线性探测法。通过资料查询和文献研究,能运用数据结构中存储结构和查找的相关理论知识,对哈希函数构造算法、哈希冲突的解决方法的效率进行实现和分析,并证实解决方案的合理性,并回答以下问题。
1、写出哈希表的基本概念
哈希表,又称为散列表,是一种根据键来直接访问内存位置的一种数据结构。它通过一个计算键值的函数(散列函数)来将所查询的数据映射到哈希表中的一个位置来查找该位置的内容,从而达到快速查找的目的。普通的数据结构中查找某一个关键字通常需要遍历整个数据结构,时间复杂度O(n),而哈希表只需要O(1)的时间级。
2、列出常用的哈希函数构造方法,并阐述各自的特点。
构造哈希函数的目标是使所有元素的哈希地址尽可能均匀的分布在m个连续内存单元上,同时使计算过程尽可能简单以达到尽可能高的时间效率。
常用的哈希函数构造方法有:直接定址法,除留余数法,数字分析法等。
直接定址法
定义:以关键字k本身或关键字加上某个常量c作为哈希地址的方法。
哈希函数:h(k)=k+c.
特点:哈希函数计算简单。当关键字的分布基本连续时,可用直接定制法的哈希函数;否则,若关键字的分布不连续将造成内存单元的大量浪费。由于直接定址法所得的地址集合和关键字集合的大小相同,因此对于不同的关键字不会发生冲突,但是实际中能使用这种哈希函数的情况比较少。
除留余数法
定义:用关键字k除以某个不大于哈希表长度m的整数p所得的余数作为哈希表地址。
哈希函数:h(k)=k mod p (mod 求余运算,p<=m).
特点:计算比较简单,适用范围广,是最经常使用的一种哈希函数。这种方法的关键是p要选好,使得元素集合中的每一个关键字通过该函数转换后映射到哈希表范围内的任意地址上的概率相等,从而尽可能减少发生冲突的可能性。
数字分析法
定义:提取关键字中取值较均匀的数字位作为哈希地址。假设关键字是以r为基的数,并且哈希表中可能出现的关键字都是事先知道的,则可以取关键字的若干位组成哈希地址。
特点:适用于关键字位数比哈希地址位数大,且关键字已知。
其他构造整数关键字的哈希函数的方法:
平方取中法
定义:取关键字的平方后的中间几位为散列地址,位数由表长决定。
特点:这是一种比较常用的方法,通常在选定哈希函数时不一定能知道关键字的全部情况,因此去其中的哪几位不一定合适,而一个数的平方后的中间几位是和一个数的每一位都相关,由此使随即分布的关键字得到的哈希地址也是随机的。
折叠法
定义:关键字分割成位数相同的几部分(最后一部分的位数可以不同),然后取这几部分的叠加和(舍去进位)。
3、列出常见的解决哈希冲突的方法,并阐述各自的优缺点。
常见的解决哈希冲突的方法有:
开放定址法:线性探测法、随机探测法、二次探测法、链地址法、公共溢出区法
开放定址法
当一个关键字和另一个关键字发生冲突时,使用某种探测技术在Hash表中形成一个探测序列,然后沿着这个探测序列依次查找下去,当碰到一个空的单元时,则插入其中。
①线性探测:以增量序列 1,2,……,(TableSize -1)循环试探下一个存储地址,即di = i。如果table[index+di]为空则进行插入,反之试探下一个增量。线性探测法的优点是解决冲突简单,线性探测也有弊端,就是会造成元素聚集现象,降低查找效率。
②平方探测法:以增量序列1,-1,4,-4…且q ≤ TableSize/2 循环试探下一个存储地址。平方检测法的优点是可以避免出现堆积问题,缺点是不一定能探测到哈希表上的所有单元,但最少能探测到一单元。
拉链法
是将所有关键字为同义词的结点链接在同一个单链表中 。链接法的构思来源于链表的启发,将被哈希到哈希表同一位置的数通过链表进行连接,使得他们能够在哈希表中共存,从而解决了哈希冲突。
与开放定址法相比,拉链法有如下几个优点:
①链地址法处理冲突简单,且无堆积现象,即非同义词决不会发生冲突,因此平均查找长度较短;
②由于链地址法中各链表上的结点空间是动态申请的,故它更适合于造表前无法确定表长的情况;
③开放定址法为减少冲突,要求装填因子α较小,故当结点规模较大时会浪费很多空间。而链地址法中可取α≥1,且结点较大时,链地址法中增加的指针域可忽略不计,因此节省空间;
④在用链地址法构造的散列表中,删除结点的操作易于实现。只要简单地删去链表上相应的结点即可。而对开放地址法构造的散列表,删除结点不能简单地将被删结 点的空间置为空,否则将截断在它之后填人散列表的同义词结点的查找路径。这是因为各种开放地址法中,空地址单元(即开放地址)都是查找失败的条件。
拉链法的缺点是:指针需要额外的空间,故当结点规模较小时,开放定址法较为节省空间,而若将节省的指针空间用来扩大散列表的规模,可使装填因子变小,这又减少了开放定址法中的冲突,从而提高平均查找速度。
4、写出影响哈希查找性能的3个主要因素。
在查找过程中,关键字的比较次数,取决于产生冲突的多少,产生的冲突少,查找效率就高,产生的冲突多,查找效率就低。因此,影响产生冲突多少的因素,也就是影响查找效率的因素。影响产生冲突多少有以下三个因素:
- 散列函数是否均匀
- 处理冲突的方法
- 散列表的装填因子
5、计算各关键字存储地址的过程,并完成表1中所构造的哈希表。
采用哈希函数:H(key)=(key*3) % 7,处理冲突采用线性探测法
H(7)=(7*3)%7=0
H(8)=(8*3)%7=3
H(30)=(30*3)%7=6
H(11)=(11*3)%7=5
H(18)=(18*3)%7=5
H(9)=(9*3)%7=6
H(14)=(14*3)%7=0
线性探测再散列:
index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|---|
key | 7 | 8 | 11 | 30 | ||||||
18冲突后移 | 18冲突后移 | 18 | ||||||||
9冲突后移 | 9冲突后移 | 9 | ||||||||
14冲突后移 | 14 | |||||||||
最终结果 | 7 | 14 | 8 | 11 | 30 | 18 | 9 |
综上,表1构造的哈希表结果如下:
6、分别计算等概率情况下查找成功和查找不成功的平均查找长度。
等概率情况下查找成功:
关键字7、8、11、30都是一次就填入了表中,因此查找次数为1; 关键字9、18进行了3次放入操作,查找次数都为3;关键字14进行了两次探测,因此查找次数为2。
所以总的查找成功的平均查找长度:
ASL成功= (1+2+1+1+1+3+3)/ 7 = 12/7= 1.714
等概率情况下查找不成功:
地址0,到第一个关键为空的地址2的距离为3,因此查找不成功的次数为3.
地址1,到第一个关键为空的地址2的距离为2,因此查找不成功的次数为2.
地址2,到第一个关键为空的地址2的距离为1,因此查找不成功的次数为1.
地址3,到第一个关键为空的地址4的距离为2,因此查找不成功的次数为2.
地址4,到第一个关键为空的地址4的距离为1,因此查找不成功的次数为1.
地址5,到第一个关键为空的地址2的距离为5,因此查找不成功的次数为5.
地址6,到第一个关键为空的地址2的距离为4,因此查找不成功的次数为4.
查找不成功的平均查找长度:
ASL失败= (3+4+2+2+1+1+5)/ 7 = 18/7= 2.571