实现字典的一种有效数据结构为散列表,散列表是普通数组概念的推广,像数组一样可以直接寻址。
1.直接寻址表
当全域u较小时,使用直接寻址法简单有效。
为表示动态集合,我们用一个数组(或称为直接寻址法)T[0....m-1],其中每个位置(或称槽)
对应全域U中的一个关键字。如下图altomithm001所示方法;槽k指向集合中一个关键字为k的元素。
如果该集合中没有关键字为k的元素,则T[k]=NULL.
altomithm001
operation:
direct_address_search(T, k)
return T[k];
direct_address_insert(T, x)
x->X;
key[x];
T[ key[x ]] = X;
derict_address_delete(T, x)
key[x];
T[key[x]] = NULL;
2 散列表
散列函数的目的就是在于缩小需要处理的下表范围,将|U|降到m. 进而降低了T[0...m-1]的大小,降低空间的开销。
altomithm002
这样做将会带来一个问题,两个关键字可能映射到同一个槽上。即碰撞(collision)
解决方法:链接法(chaining),开放寻址法等
链接法:把散列到同一槽中的所有元素都放在一个链表中。
altomithm003
3 散列函数
好的散列函数:每个关键字都等可能地散列到m个槽位的任何一个中去,并于其他的关键字已被散列到哪一个槽位中无关。
除法散列,用一个特定的质数来除所给定的关键字,所得的余数即为该关键字的散列值。
将关键字解释为自然数:多数的散列函数都假设关键字域为自然数集N={0,1,2,3.....}.如果所给关键字不是自然数,则必须有
一种方法将他们解释为自然数。
除法散列法
h(k) = k mod m; 其中 要注意m的选择 例如,m不应是2的幂。
乘法散列法
首先,用关键字k乘上常数A(0<A<1),并抽取出kA的小数部分,然后,用m乘以这个值。最后取结果的底。
全域散列
开放寻址法
完全散列