基本思想:在记录的存储地址和它的关键字之间建立一个确定的对应关系;
这样,不经过比较,一次存取就能得到所查元素的查找方法。


哈希函数:在记录的关键字与记录的存储地址之间建立的一种对应关系叫哈希函数。
哈希函数是一种映象,是从关键字空间到存储地址空间的一种映象。
可写成:addr(ai)=H(ki) ,其中i是表中一个元素,
addr(ai)是ai的地址, ki是ai的关键字。
哈希表:应用哈希函数,由记录的关键字确定记录在表中的地址,
并将记录放入此地址,这样构成的表叫哈希表。
哈希查找(又叫散列查找):利用哈希函数进行查找的过程叫哈希查找。       


冲突:对于不同的关键字ki、kj,若ki?kj,但H(ki)=H(kj)的现象叫冲突(collision) 。
      同义词:具有相同函数值的两个不同的关键字,称为该哈希函数的同义词。
        哈希函数通常是一种压缩映象,所以冲突不可避免,只能尽量减少;
当冲突发生时,应该有处理冲突的方法。设计一个散列表应包括:
①  散列表的空间范围,即确定散列函数的值域;
②  构造合适的散列函数,使得对于所有可能的元素(记录的关键字),函数值均在散列表的地址空间范围内,且出现冲突的可能尽量小; 
③  处理冲突的方法。即当冲突出现时如何解决。


哈希函数是一种映象,其设定很灵活,只要使任何关键字的哈希函数值都落在
表长允许的范围之内即可。哈希函数“好坏”的主要评价因素有:
◆  散列函数的构造简单;
◆ 能“均匀”地将散列表中的关键字映射到地址空间。所谓“均匀”(uniform)是指发生冲突的可能性尽可能最少。






1  直接定址法
        取关键字或关键字的某个线性函数作哈希地址,即H(key)=key    或   H(key)=a·key+b(a,b为常数)
       特点:直接定址法所得地址集合与关键字集合大小相等,不会发生冲突,但实际中很少使用。


2  数字分析法
        对关键字进行分析,取关键字的若干位或组合作为哈希地址。
       适用于关键字位数比哈希地址位数大,且可能出现的关键字事先知道的情况。


3  平方取中法
       将关键字平方后取中间几位作为哈希地址。
       一个数平方后中间几位和数的每一位都有关,则由随机分布的关键字得到的散列地址也是随机的。散列函数所取的位数由散列表的长度决定。这种方法适于不知道全部关键字情况,是一种较为常用的方法。


4  折叠法
        将关键字分割成位数相同的几部分(最后一部分可以不同),然后取这几部分的叠加和作为哈希地址。
       数位叠加有移位叠加和间界叠加两种。


5  除留余数法
        取关键字被某个不大于哈希表表长m的数p除后所得余数作哈希地址,即H(key)=key   MOD  p     (p?m)
        是一种简单、常用的哈希函数构造方法。
        利用这种方法的关键是p的选取,p选的不好,容易产生同义词。p的选取的分析:
 ◆  选取p=2i(p?m):运算便于用移位来实现,但等于将关键字的高位忽略而仅留下低位二进制数。高位不同而低位相同的关键字是同义词。
 ◆ 选取p=q?f(q、f都是质因数,p?m):则所有含有q或f因子的关键字的散列地址均是q或f的倍数。 
 ◆ 选取p为素数或p=q?f(q、f是质数且均大于20,p?m):常用的选取方法,能减少冲突出现的可能性。


6  随机数法
      取关键字的随机函数值作哈希地址,即H(key)=random(key)
当散列表中关键字长度不等时,该方法比较合适。
选取哈希函数,考虑以下因素
◆ 计算哈希函数所需时间;
◆ 关键字的长度;
◆ 哈希表长度(哈希地址范围);
◆ 关键字分布情况;
◆ 记录的查找频率。




ELFhash字符串散列函数:


结果h先初始化为0,循环地将一个字符串数组中的每个元素依次处理,上次结果h左移四位,与当前元素相加,
组成一个新长整数h,取h的高四位存入g中,如果g不为0,那么,把g右移24位,即把g的高四位移到低四位。
然后h进行按位异或操作,g取反,然后和h进行按位与运算,得到新的h,最后得到的长整数h对散列表长
取余,得到相应的散列数值,即在散了表中的位置。