动态查找表--哈希表--构造哈希函数

散列函数的选择有两条标准:简单和均匀。
     简单指散列函数的计算简单快速;
     均匀指对于关键字集合中的任一关键字,散列函数能以等概率将其映射到表空间的任何一个位置上。也就是说,散列函数能将子集K随机均匀地分布在表的地址集{0,1,…,m-1}上,以使冲突最小化。


       函数的运算应尽可能地简单;函数的值域必须在散列表的范围内;关键字值的集合由散列函数映射得到的地址集合均匀分布在散列表范围内,即尽可能使存取结点在散列表中均匀分布;尽可能减少冲突。


选取散列函数,考虑以下因素:

    >>计算散列函数所需时间

    >>关键字长度

    >>散列表长度(散列地址范围)

    >>关键字分布情况

    >>记录的查找频率


(1)直接定址法

构造:取关键字或关键字的某个线性函数作散列地址,即H(key)=key     

                    或   H(key)=a.key+b

比如:统计从1岁到99岁的人口数字统计表,其中年龄作为关键字,哈希函数取关键字自身     

特点:

     直接定址法所得地址集合与关键字集合大小相等,不会发生冲突,实际中能用这种哈希函数的情况很少

2)数字分析法

    构造:对关键字进行分析,取关键字的若干位或其组合作散列地址

特点:适于关键字位数比散列地址位数大,且可能出现的关键字事先知道的情况

例  有80个记录,关键字为8位十进制数,哈希地址为2位十进制数

 

(3)平方取中法

    构造:取关键字平方后中间几位作哈希地址

    特点:适于不知道全部关键字情况

先通过求关键字的平方值扩大相近数的差别,然后根据表长度取中间的几位数作为散列函数值。又因为一个乘积的中间几位数和乘数的每一位都相关,所以由此产生的散列地址较为均匀。

【例】将一组关键字(0100,0110,1010,1001,0111)平方后得
    (0010000,0012100,1020100,1002001,0012321)
   若取表长为1000,则可取中间的三位数作为散列地址集:
    (100,121,201,020,123)。
相应的散列函数用C实现很简单:
int Hash(int key){ //假设key是4位整数
  key*=key; key/=100; //先求平方值,后去掉末尾的两位数
  return key%1000; //取中间三位数作为散列地址返回
 }

(4)折叠法

    构造:将关键字分成位数为 t 的若干段(最后一段的位数可能小于t),然后取这几部分的叠加和(舍去进位)做哈希地址。

 种类:

    移位叠加:将分割后的几部分低位对齐相加

    间界叠加:从一端沿分割界来回折送,然后对齐相加

  特点:适于关键字位数很多,且每一位上数字分布大致均匀情况

5)除留余数法

  该方法是最为简单常用的一种方法。它是以表长m来除关键字,取其余数作为散列地址,即 h(key)=key%m
     该方法的关键是选取m。选取的m应使得散列函数值尽可能与关键字的各位相关。m最好为素数。
   【例】若选m是关键字的基数的幂次,则就等于是选择关键字的最后若干位数字作为地址,而与高位无关。于是高位不同而低位相同的关键字均互为同义词。
   【例】若关键字是十进制整数,其基为10,则当m=100时,159,259,359,…,等均互为同义词。

6)随机数法

 选择一个随机函数,取关键字的随机函数值为它的散列地址,即
         h(key)=random(key)
   其中random为伪随机函数,但要保证函数值是在0到m-1之间。

posted @ 2012-02-05 20:42  nba76ers  阅读(704)  评论(0)    收藏  举报