实现字典的一种有效数据结构为散列表,散列表是普通数组概念的推广,像数组一样可以直接寻址。

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]的大小,降低空间的开销。

散列表_数组_02

                                              altomithm002

这样做将会带来一个问题,两个关键字可能映射到同一个槽上。即碰撞(collision)

解决方法:链接法(chaining),开放寻址法等

链接法:把散列到同一槽中的所有元素都放在一个链表中。

散列表_散列函数_03

 

                                                 altomithm003

3 散列函数

好的散列函数:每个关键字都等可能地散列到m个槽位的任何一个中去,并于其他的关键字已被散列到哪一个槽位中无关。

除法散列,用一个特定的质数来除所给定的关键字,所得的余数即为该关键字的散列值。

将关键字解释为自然数:多数的散列函数都假设关键字域为自然数集N={0,1,2,3.....}.如果所给关键字不是自然数,则必须有

一种方法将他们解释为自然数。

除法散列法  

            h(k) = k mod m;   其中 要注意m的选择 例如,m不应是2的幂。

乘法散列法

            首先,用关键字k乘上常数A(0<A<1),并抽取出kA的小数部分,然后,用m乘以这个值。最后取结果的底。

全域散列

 

开放寻址法

          

完全散列