#1.Hash表
哈希表(Hash table,也叫散列表),是根据key而直接进行访问的数据结构。也就是说,它通过把key映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
以数据中每个元素的关键字K为自变量,通过散列函数H(k)计算出函数值,以该函数值作为一块连续存储空间的的单元地址,将该元素存储到函数值对应的单元中。
哈希表存储的是键值对,其查找的时间复杂度与元素数量多少无关,哈希表在查找元素时是通过计算哈希码值来定位元素的位置从而直接访问元素的,因此,哈希表查找的时间复杂度为O(1)。
#2.哈希表的构造方法
##2.1直接定址法
取关键字或者关键字的某个线性函数值作为哈希地址,即 H(Key)=Key或者H(Key)=a*Key+b(a,b为整数) 这种散列函数也叫做自身函数.如果H(Key)的哈希地址上已经有值了,那么就往下一个位置找,直到找到H(Key)的位置没有值了就把元素放进去. 此法仅适合于:地址集合的大小 等于 关键字集合的大小
##2.2 数字分析法
分析一组数据,比如一组员工的出生年月,这时我们发现出生年月的前几位数字一般都相同,因此,出现冲突的概率就会很大,但是我们发现年月日的后几位表示月份和具体日期的数字差别很大,如果利用后面的几位数字来构造散列地址,则冲突的几率则会明显降低. 因此数字分析法就是找出数字的规律,尽可能利用这些数据来构造冲突几率较低的散列地址. 此法适于:能预先估计出全体关键字的每一位上各种数字出现的频度。 ##2.3 平方取中法
以关键字的平方值的中间几位作为存储地址(哈希地址)。求“关键字的平方值” 的目的是“扩大差别” ,同时平方值的中间各位又能受到整个关键字中各位的影响。
此法适于:关键字中的每一位都有某些数字重复出现频度很高的现象。 ##2.4 折叠法
将关键字分割成若干部分,然后取它们的叠加和为哈希地址。两种叠加处理的方法:移位叠加:将分 割后的几部分低位对齐相加;间界叠加:从一端沿分割界来回折叠,然后对齐相加。 此法适于:关键字的数字位数特别多。
##2.5随机数法
设定哈希函数为:H(key) = Random(key)其中,Random 为伪随机函数 此法适于:对长度不等的关键字构造哈希函数。
##2.6除留余数法
取关键字被某个不大于散列表表长m的数p除后所得的余数为散列地址.即 哈希函数为:H(key) = key MOD p ( p≤m ),其中, m为表长,p 为不大于 m 的素数。
#3.哈希表冲突解决方法
哈希表处理冲突主要有开放寻址法、再散列法、链地址法(拉链法)和建立一个公共溢出区四种方法。 通过构造性能良好的哈希函数,可以减少冲突,但一般不可能完全避免冲突,因此解决冲突是哈希法的另一个关键问题。 “处理冲突” 的实际含义是:为产生冲突的关键字寻找下一个哈希地址。 ##3.1开放定址法 一旦发生了冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入。
###3.1.1线性探测
冲突发生时,顺序查看表中下一单元,直到找出一个空单元或查遍全表。
公式:
fi(key) = (f(key)+di) MOD m (di=1,2,3,......,m-1)
###3.1.2二次探测法
冲突发生时,在表的左右进行跳跃式探测,双向寻找到可能的空位置。
公式:
fi(key) = (f(key)+di) MOD m (di = 12, -12, 22, -22,……, q2, -q2, q <= m/2)
###3.1.3随机探测法
在冲突时,对于位移量 di 采用随机函数计算得到,我们称之为随机探测法。
公式:
fi(key) = (f(key)+di) MOD m (di是一个随机数列)
线性探测再散列容易产生“二次聚集”,即在处理同义词的冲突时又导致非同义词的冲突。 线性探测再散列的优点是:只要哈希表不满,就一定能找到一个不冲突的哈希地址,而二次探测再散列和伪随机探测再散列则不一定。
##3.2链地址法
将所有哈希地址相同的记录都链接在同一链表中。各链表上的结点空间是动态申请的,故它更适合于造表前无法确定表长的情况。 处理冲突简单,且无堆积现象,即非同义词决不会发生冲突,因此平均查找长度较短;
##3.3再哈希法
这种方法是同时构造多个不同的哈希函数:
Hi=RH1(key),i=1,2,3,…,n.
当哈希地址Hi=RH1(key)发生冲突时,再计算Hi=RH2(key)……,直到冲突不再产生。这种方法不易产生聚集,但增加了计算时间。
##3.4建立公共溢出区
这种方法的基本思想是:将哈希表分为基本表和溢出表两部分,凡是和基本表发生冲突的元素,一律填入溢出表.(注意:在这个方法里面是把元素分开两个表来存储)