算法导论散列表笔记

直接寻址表

全域 U 比较小,不需要散列函数,直接将全域的每个元素都映射到表中。书中没有给出具体的应用场景,个人感觉应用不广,价值不大。

散列表

正常的散列表需要用散列函数,将全域中的关键词散列到有限大小的表中。
散列函数面临冲突问题,即不同的关键字散列到同一个位置。这一节介绍了链表法,后面还有开放寻址法。
链表法是将冲突的元素存放在一个链表中,散列表中存放链表的表头。
性能分析可以得出,正常情况下散列表的所有操作都可以在 O(1) 时间内完成,速度非常快,值得拥有。

散列函数

除法散列法,将关键字转化成一个数字k,然后对表的大小(散列表的槽数)取余,即完成映射。
乘法散列法,将k(数字)乘以常数A后取小数部分,再乘以m(表的大小)并向下取整,即完成映射。
一直认为散列函数是一个复杂的问题,感觉上面两种方法都比较简单,可能不是很实用。
全域散列法,核心思想也比较简单,利用数论的知识设计一组形式简单的散列函数
“全域” 是散列函数的一个性质,书中先给出了全域的概念,然后是性能分析,最后提出了如何设计一个函数族,并证明这个函数族是全域的。
此处还是有一个疑问,如果散列函数是一组函数,在进行关键字散列时是随机选择的,那么这个选择的机制是如何的,如何保证同一个关键字每次散列都选中同一个函数

开放寻址法

开放寻址法是利用另一种思路解决冲突问题(不同于链表法),思想是给每个关键字生成一个探查序列,如果发生冲突就继续检查探查序列的下一个位置
探查序列如何生成:线性探查,二次探查,双重散列
双重散列的性能最好,区别只是在散列函数的选取上有所不同
个人觉得这种方法缺点明显:

  1. 不能存储超过散列表大小的元素
  2. 对删除操作也不友好
  3. 散列表越满,性能越差
    但是总体说来性能也可以接受,一般的访问存取在常数时间内

完全散列

完全散列在最坏情况下也能用O(1) 时间内完成访存
它的思路是用两级散列,第一级散列是普通的散列,第二级散列将第一级散列中散列到同一个槽中的关键字再次散列到一个散列表中
其中的关键是第二次散列设计为不会产生冲突,可以在O(1) 时间内完成访问
为了确保这一点,二级散列表的大小被设置为 n 的平方,散列函数的选取需要尝试,可以证明能够比较容易的选取(几次尝试)可以使关键字没有冲突的散列函数
书中后面又给出了证明,完全散列法对空间的需求为 O(n) 数量级
堪称完美的散列方法,但不知为什么书中这一节加星,或许不是很常用,对性能追求到了极限

关于全域散列法的补充

之前没有明白全域散列法是如何随机选取散列函数的,看完完全散列后,感觉应该是每个散列表随机选择一个散列函数,这张表选定后就一直使用同一个函数

你可能感兴趣的:(算法导论散列表笔记)