码迷,mamicode.com
首页 > 其他好文 > 详细

哈希表

时间:2015-03-17 11:57:07      阅读:163      评论:0      收藏:0      [点我收藏+]

标签:

1.哈希(Hash)函数

  如果能在关键字与记录保存的位置之间建立一种联系,则可以不经过比较,直接对关键字进行计算得出记录保存的位置,再到相应位置去读取数据即可。将这种关键字与记录保存位置之间的对应关系称为哈希(Hash)函数,将按这种方式建立的表称为哈希表。

2.哈希表的基本思想是:以线性表中每个元素的关键字key为自变量,通过一定的函数关系h(key)计算出函数的值,把这个值作为数组的下标,将元素存入对应的数组元素中。

  函数h(key)称为哈希函数,函数的值称为哈希地址。

  在查找时,根据关键字key,用同样的哈希函数h(key)计算得出哈希地址,然后到相应的数组中取出要找的元素。

3.构造哈希函数

  (1)直接定址法

  直接定址法是以关键字key本身或关键字key加上某个常数C,用来作为哈希地址,即

              h(key) = key + C

  当C为0时,哈希地址就是关键字本身。

  (2)除法取余法

  除法取余法就是用关键字key除以散列表长度n,得到的余数作为哈希地址。

  (3)数字分析法

  数字分析法是取关键字key中某些比较分散的数字作为散列地址的方法。  

  (4)平方取中法

  平方取中法是将关键字key求平方后,取中间的几位数字作为哈希地址的方法。

  (5)折叠法

  折叠法是先将关键字key按哈希地址要求的位数分成长度相等的几段,最后一段的长度可能会短些。接着将这几段进行求和,然后去掉最高位的进位,将得到的值作为散列地址。

4.处理冲突

  (1)开放地址法

  所谓开放地址,就是哈希表中尚未使用的数组元素的地址。

  开放地址法就是从发生冲突的那个数组元素开始,按一定的次序,从哈希表中查出一个空闲的数组元素,把发生冲突的待插入元素存入到该数组元素中。

  使用开放地址法解决冲突,其主要就是需要寻找开放地址。需找开放地址的方法通常有线性探测法和双散列探测法两种。

  1)线性探测法从发生冲突的单元起,在哈希表中按顺序向后探测,直到找到开放地址为止,若到哈希表末尾仍未找到开放地址,则放回哈希表的首端再向后探测。这样,只要表中有开放地址,总会被找到。

  2)双散列函数探测法

  双散列函数探测法使用两个散列函数h和h1,其中h为主散列函数,h1为次散列函数。当由h(key)计算的地址被占用时,向后移动h1(hey)个单元再探测开放地址,若探测的地址仍不是开放的,可逐次向后移h1(key)个单元进行探测,若到散列表的末尾仍未找到开放地址,则从散列表的首端再向后探测,直到找到开放地址为止。

  (2)链接法

  链接法是在哈希表的每个存储单元中增设一个指针域,将哈希地址相同的元素链接起来。

  这种方法将占用更多的内存空间,但其优点是查找速度快,不需进行多次探测。

5.哈希表的查找

 1 //----------------开放定址哈希表的存储结构-----------------------
 2 int hashsize[] = {997,...};        //哈希表容量递增表,一个合适的素数序列
 3 typedef struct{
 4     ElemType *elem;            //数据元素存储基址,动态分配数组
 5     int  count;                        //当前数据元素个数
 6     int  sizeindex;                //hashsize[sizeindex]为当前容量
 7 }HashTable;
 8 
 9 #define  SUCCESS 1
10 #define UNSUCCESS 0
11 #define DUPLICATE -1
12 
13 Status SearchHash(HashTable H,KeyType K,int &p,int &c){
14     //在开放地址哈希表H中查找关键码为K的元素,若查找成功,以p指示待查数据元素在表中位置,并返回SUCCESS;否则,以p指示插入位置,并返回UNSUCCESS,c用以计冲突次数,其初值置零,供建表插入时参考
15     p = Hash(K);                //求得哈希地址
16     while(H.elem[p].key != NULLKEY && !EQ(K,H.elem[p].key))        //该位置中填有记录并且关键字不相等
17       collision(p,++c);            //求得下一探查地址p
18     if EQ(K,H.elem[p].key)       
19         return SUCCESS;        //查找成功,p返回待查数据元素位置
20     else 
21       return   UNSUCCESS;    //查找不成功(H.elem[p].key == NULLKEY),p返回的是插入位置
22 }//SearchHash
 1 //----------通过调用查找算法实现了开放定址哈希表的插入操作------------
 2 Status InsertHash(HashTable &H,Elemtype e){
 3     //查找不成功时插入数据元素e到开放定址哈希表H中,并返回OK;若冲突次数过大,则重建哈希表
 4     c = 0;
 5     if(SearchHash(H,e.key,p,c))
 6         return DUPLICATE;        //表中已有与e有相同关键字的元素
 7     else if(c<hashsize[H.sizeindex]/2){    //冲突次数c未达到上限,(c的阀值可调)
 8         H.elem[p] = e; ++H.count; return OK;    //插入e
 9         }
10     else
11         {RecreateHashTable(H);return UNSUCCESS;}    //重建哈希表
12 }//InsertHash

 

哈希表

标签:

原文地址:http://www.cnblogs.com/wxb713/p/4343873.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!