静态查找表和动态查找表中,数据元素的存放位置和数据元素的关键字之间没有任何关系,因此他们的查找是一系列的比较过程。
如果我们自己构造一个查找表,使得数据元素的存放位置和数据元素之间存在某种关系,则我们就可以直接通过数据元素的关键字
得到该数据元素的存放位置。(这种查找表就是哈希查找表)我们把数据元素的关键字和该数据元素的存放位置之间的映射函数称之为
哈希函数。因此可以说,哈希表是通过哈希函数来确定数据元素存放位置的一种特殊的表结构。
哈希表是一种数据结构,提供快速的插入和查找操作。不论哈希表中有多少数据,插入和删除只需要接近常量的时间极0(1)的时间级,实际上,这只需要几条机器指令即可。
对哈希表的使用者来说,这是一瞬间的事情,哈希表运算非常快,机器程序中,如果需要在一秒钟内查找上千条记录通常使用hashtable,不仅速度快,编程实现也相对容易。
缺点是它是基于数组的,数组创建后,难于扩展,某些哈希表被基本填满时候,性能下降的厉害,所以程序员必须要清楚表中将要存储多少数据。
而且没有一种简便的方法可以以任何一种顺序遍历表中的数据。如果需要这种能力,就只能选择其他数据结构。
一、哈希表算法-哈希表的概念和作用。
一般的线性表,树中,记录在结构中的相对位置是随机的,即和记录的关键字之间不存在确定的关系,因此,在结构中查找记录时需进行一系列和关键字的比较。这一类查找方法建立在“比较“的基础上,查找的效率依赖于查找过程中所进行的比较次数。
理想的情况是能直接找到需要的记录,因此必须在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使每个关键字和结构中一个唯一的存储位置相对应。
哈希表最常见的例子是以学生学号为关键字的成绩表,1号学生的记录位置在第一条,10号学生的记录位置在第10条...
如果将来要查找王帅的成绩,可以用名字首字母之和代表的符号来查出该记录的位置。23+19=43取出第43条记录就好了。问题:若是一个叫刘立,一个叫刘丽,如和处理比较好?
这个问题是哈希表不可避免的,就是冲突现象,对不同的关键字可能得到同一个哈希地址。
二、哈希算法,哈希表的构造方法。
1、直接定址法:
2、数字分析法:
3、平方取中法:
4、折叠法:
将关键字分割成位数相同的几部分(最后一部分的位数可以不同),然后取这几部分的叠加和(舍去进位)作为哈希地址,这方法称为折叠法。
例如:每一种西文图书都有一个国际标准图书编号,它是一个10位的十进制数字,若要以它作关键字建立一个哈希表,当馆藏书种类不到10,000时,可采用此法构造一个四位数的哈希函数。如果一本书的编号为0-442-20586-4,则:
5、除留余数法
取关键字被某个不大于哈希表表长m的数p除后所得余数为哈希地址。
H(key)=key MOD p (p<=m)
6、随机数法
选择一个随机函数,取关键字的随机函数值为它的哈希地址,即
H(key)=random(key) ,其中random为随机函数。通常用于关键字长度不等时采用此法。
5、除留余数法
取关键字被某个不大于哈希表表长m的数p除后所得余数为哈希地址。
H(key)=key MOD p (p<=m)
6、随机数法
选择一个随机函数,取关键字的随机函数值为它的哈希地址,即
H(key)=random(key) ,其中random为随机函数。通常用于关键字长度不等时采用此法。
5、除留余数法
取关键字被某个不大于哈希表表长m的数p除后所得余数为哈希地址。
H(key)=key MOD p (p<=m)
6、随机数法
选择一个随机函数,取关键字的随机函数值为它的哈希地址,即
H(key)=random(key) ,其中random为随机函数。通常用于关键字长度不等时采用此法。
三、哈希表中处理冲突的算法:
如果两个同学分别叫 刘丽 刘兰,当加入刘兰时,地址24发生了冲突,我们可以以某种规律使用其它的存储位置,如果选择的一个其它位置仍有冲突,则再选下一个,直到找到没有冲突的位置。选择其它位置的方法有:
1、开放定址法:
Hi=(H(key)+di) MOD m i=1,2,...,k(k<=m-1)
其中m为表长,di为增量序列
如果di值可能为1,2,3,...m-1,称线性探测再散列。
如果di取值可能为1,-1,2,-2,4,-4,9,-9,16,-16,...k*k,-k*k(k<=m/2)
称二次探测再散列。
如果di取值可能为伪随机数列。称伪随机探测再散列。
2、再哈希法
当发生冲突时,使用第二个、第三个、哈希函数计算地址,直到无冲突时。缺点:计算时间增加。
3、链地址法
将所有关键字为同义词的记录存储在同一线性链表中。
4、建立一个公共溢出区
假设哈希函数的值域为[0,m-1],则设向量HashTable[0..m-1]为基本表,另外设立存储空间向量OverTable[0..v]用以存储发生冲突的记录。