【算法导论】第十一章 散列表 学习笔记

散列表

散列表(hash table)是实现字典操作的一种有效数据结构。尽管在最坏的情况下,在散列表中的查找一个元素的时间与链表中查找的时间相同,为 O ( n ) 。在一下合理的假设下,在散列表中查找一个元素的时间复杂度为 O ( 1 ) 。在散列表中不是直接把关键字作为数组的下标,而是根据关键字计算出相应的下标。

直接寻址表

当关键字的全域 U 比较小时,直接寻址法是简单而有效的。设 U = 0 , 1 , 2 , , m 1 ,且假设任意两个元素不具有相同的关键字。则数组的大小应为m。

散列表

直接寻址技术的显著缺点是:如果全域 U 非常大,则在一台标准的计算机可用内存中,要存储大小为 | U | 的一张表 T 非常不现实。并且,实际存储的关键字集合 K 相对 U 来说也许很小。这样分配给 T 的空间就大部分被浪费了。

散列表即:利用散列函数(hash function) h ( k ) ,有关键字 k 计算出槽的位置,函数 h 将关键字的全域 U 映射到散列表(hash table)的槽位上。

存在问题:两个关键字可能会映射到同一个槽中,这叫冲突。如何解决这种冲突?

  1. 尽量避免冲突:试图选择一个散列函数能避免冲突或使冲突次数最小化。实际上,散列这个术语的原意就是随机混杂和拼凑,即体现了这种思想。
  2. 完全避免冲突几乎是不可能的,所以还是需要有解决冲突的办法
    1. 链接法
    2. 开放寻址法

链接法

操作的时间复杂度:

插入HASH_INSERT(T,x):在链表表头进行插入O(1),前提是假设插入的元素没有出现在表中。否则需要先查找

删除HASH_DELETE(T,x):O(1),前提是假设链表为双向链表(这里没看懂,为什么双向链表可以不用在T中找x?)。否则需要先找到x的前驱节点,这样复杂度就等同于查找的复杂度。

查找HASH_SEARCH(T,k):定义T的装载因子 α = n / m ,即一个链表的平均存储元素个数。则查找操作的时间复杂度由两部分组成:

  • 查找失败: Θ ( 1 + α ) ,在简单均匀散列的假设下,任何尚未被存储在表中的关键字k,都等可能的被散列到m个槽中,在槽中的查找时间为 Θ ( α ) ,1则为计算 h ( k ) 的时间
  • 查找成功: Θ ( 1 + α ) ,根据复杂计算所得…

所以查找操作的时间复杂度为 Θ ( 1 + α ) 。这意味着,如果散列表中槽数至少与表中的元素个数成正比,则查找操作平均也只需要常数的时间—— O ( 1 )

思考:

扫描二维码关注公众号,回复: 1059502 查看本文章

算法导论练习题:11.2-3

题目:对链表法进行改进,保证链表有序,则散列性能能得到较大的提高。试分析这种改动对成功查找、失败查找、插入和删除的运行时间各有什么影响?

  • 插入:由于链表有序,用插入排序比较合适,此时为时间复杂度为 O ( n / m ) = O ( α )
  • 成功查找和失败查找:二分法 O ( l g α )
  • 删除:与查找线性相关 O ( l g α )

散列函数

  1. 除法散列法
    • h ( k ) = k   m o d   m ,对m的选择敏感,m一般**不为**2的幂。
  2. 乘法散列法
    • 优点是对m的选择不敏感,m一般为2的幂。
  3. 全域散列法
    • 随机的选择散列函数,使之独立于存储的关键字k。随机化保证了没有那种输入会始终导致最坏的性能出现(类似于快排中随机选择povio)。

开放寻址法

所有元素都存放在散列表里,也就是说每个表项或包含动态集合中的一个元素,或包含NIL。当查找某个元素时,要系统的检查所有的表项,直到找到所需元素,或最终查明改元素不在表中。与链表法不一样,这里既没有链表,也没有元素存放在散列表以外,因此开放寻址法中,散列表可能会被填满,且导致装载因子 α 一定不超过1。

因为不用存储指针,所以用链表法存储指针的空间在这里可以用来存储元素,即用相同的空间存储了更多的元素槽,潜在的减少了冲突提高了检索速度。

线性探查

h ( k , i ) = ( h ( k ) + i )   m o d   m ,     i = 0 , 1 , . . . , m 1

存在一次集群现象,随着连续被占用的槽不断增加,平均查找时间也不断增加。当一个空槽前有i个满的槽时,该空槽为下一个将被占用的概率是 ( i + 1 ) / m

二次探查

h ( k , i ) = ( h ( k ) + c 1 i + c 2 i 2 )   m o d   m

同样存在二次集群现象,但程度较轻。

双重散列

h ( k , i ) = ( h 1 ( k ) + i h 2 ( k ) )   m o d   m

开放寻址法分析

像在链表法中一样,开放寻址法的分析也是以散列表的装载因子 α 来表达的。

定理11.6 给定一个装载因子为 α = n / m < 1 的开放寻址散列表,并假设是均匀散列的,则对于每一次不成功的 查找,其期望探查次数至多为 1 / ( 1 α )

定理11.8 给定一个装载因子为 α = n / m < 1 的开放寻址散列表,并假设是均匀散列的,则对于每一次成功的 查找,其期望探查次数至多为 1 α l n 1 1 α

定理11.7 假设采用的是均匀散列,平均情况下,向一个装载因子为 α 的开放寻址散列表中插入一个元素至多需要 1 / ( 1 α ) 次探查。

完全散列

当关键字是静态(即关键字集合一旦存入后就不改变)时,完全散列技术也能提供出色的最坏情况性能,如果用该方法进行查找,能在最坏情况下用 O ( 1 ) 次访问完成。

猜你喜欢

转载自blog.csdn.net/tan_change/article/details/80154771
今日推荐