【算法导论】第11章,散列表

散列表是实现字典的一种数据结构,是普通数组的推广,

原理是根据关键字计算出下标,用链接的方法解决冲突。

11.1 直接寻址表

如果关键字全集比较小,可以直接寻址。

关键是将key映射成为数字,是直接计算的。如果映射规则比较复杂,导致数字的范围很大,而有效的只有很少一部分时,直接寻址法就很蠢。

11.2 散列表

用散列函数h, 计算关键字k所在的位置为 h(k)。

这一步可以产生冲突,将不同的关键字映射到同一个槽内。

介绍两种解决冲突的方法:链接法、开放寻址法

链接法:

冲突链接到同一个链表中,

插入、删除的时间都是O(1),(删除不需要搜索)。双链表删除比较快。

查找性能?

n个元素,m个槽位,装载因子 n/m

只要槽位与元素数量成正比,那么查找时间就是O(1)

11.3 散列函数

好的散列函数的标准:均匀,相近的最好不在一起,

可以将关键字转换为自然数。以下的针对关键字为自然数的情况。

除法散列法: h(k) = k mod m。如果m是2的n次幂的话要小心。

乘法散列法:h(k) = m(kA mod 1) 其中A是一个0-1之间的小数,

  优点:对m的选择不太关键,可以选择2的幂次,

全域散列法:每一个固定的散列方式都会导致存在一种状态,最差为n。

  因此要随机选择散列函数。使之独立于要储存的keys。思想是从一开始,从一族散列函数中选择一个

  全域散列族的定义为:对任意两个key,假设散列到m组中,发生冲突的散列函数 / 散列函数总数 < 1 / m

  构造全域散列族:

    输入:一个大于所有key的质数p,组数m

11.4 开放寻址法

在m组下面已经没有链表了,每个都是自己,因此装载因子小于1,

也就是m是大于整个数据量n的。

函数不是h(k) = j确定组,而是根据k和第几次尝试确定组,h(k, i) = j,要确保对于不同的i (从0到m),j是其一个全排列(从0到m)

在给出k之后,从i=0开始,看看哪一个有位置,

有三种方式:线性探查、二次探查、双重散列。

11.5 完全散列

待学习。

原文地址:https://www.cnblogs.com/yesuuu/p/8968536.html