《数据结构与算法分析》读书笔记——hash表

数据结构:哈希表

1. 散列表 / 哈希表 (hash table) 的实现叫做散列 (hashing)。

2. 理想的散列表是一个包含关键字(key)的具有固定大小(TableSize, 0~TableSize-1,数组中就是下标)的数组。

3. 关键字到下标的映射,叫做散列函数/哈希函数 (hash function)。

4. 装填因子(load factor):散列表中元素的个数与散列表大小的比值。


冲突(collision)解决办法:

1. 分离链接法(separate chaining)(数组+链表):散列到同一下标的元素建立一个链表。装填因子 ≈ 1

2. 开放定址法 (open addressing hashing):

哈希函数 hi(X) = (Hash(X) + F(i)) modTableSize , 且F(0) = 0

函数F是冲突解决函数,i 表示第 i 次冲突。一般,装填因子应该低于0.5

    线性探测法 :F是 i 的线性函数。典型:F(i) = i。  缺点:产生一次聚集(primary clustering)。即使表相对较空,也可能某些位置形成区块。

    平方探测法:F是 i 的二次函数。典型:F(i) = i2。解决一次聚集问题。缺点:产生二次聚集(secondary clustering)。散列到同一位置的那些元素将探测到相同的备选单元。

    双散列 (double hashing):F是哈希函数。典型:F(i) = i · hash2(X) 。hash2(X) = X – (X mod R),R为小于TableSize 的素数(尽量避免hash2(X)为0)。同时,表的大小也尽量为素数,保证所有的单元都能被探测到;否则备选单元可能提前用完

    

参考: http://www.cppblog.com/guogangj/archive/2009/10/15/98699.html 

斐波那契(Fibonacci)散列法:

平方散列法的缺点是显而易见的,所以我们能不能找出一个理想的乘数,而不是拿value本身当作乘数呢?答案是肯定的。

   1,对于16位整数而言,这个乘数是40503
2,对于32位整数而言,这个乘数是2654435769
3,对于64位整数而言,这个乘数是11400714819323198485

这几个“理想乘数”是如何得出来的呢?这跟一个法则有关,叫黄金分割法则,而描述黄金分割法则的最经典表达式无疑就是著名的斐波那契数列,如果你还有兴趣,就到网上查找一下“斐波那契数列”等关键字,我数学水平有限,不知道怎么描述清楚为什么,另外斐波那契数列的值居然和太阳系八大行星的轨道半径的比例出奇吻合,很神奇,对么?

对我们常见的32位整数而言,公式:
index = (value * 2654435769) >> 28


表的元素太满时,操作时间变长,插入可能失败。此时可以:

再散列:建立另外一个大约两倍大的表(而且使用一个相关的新的散列函数),扫描整个原始散列表,计算每个元素的新散列值并将其插入到新表中。表的大小通常是原表大小两倍后的第一个素数。整个操作叫做再散列(rehashing)


关于哈希表的题目:参考Julyhttp://blog.csdn.net/v_july_v/article/details/6256463


你可能感兴趣的:(《数据结构与算法分析》)