数据结构与算法-哈希表

哈希表定义:

根据设定的哈希函数H(key)和处理冲突的方法将一组关键字映像到一个有限的连续的地址集(区间)上,并以关键字在地址集中的“像”作为记录在表中的位置,这种表便称为哈希表,这一映像过程称为哈希造表或散列,所得到存储位置称哈希地址或散列地址。


前言

在顺序查找、二分查找、斐波那契查找、插值查找、最优(次优)查找树、二叉排序树、二叉平衡树、B-树等查找方法中,记录的位置相对是随机的,在查找记录时依赖与关键字的比较(有><=三种情况)。因此以上查找的效率依赖查找过程中进行比较的次数。
若能将所查记录与其存储位置建立一个对应关系f,使每个记录中关键字与其存储位置一一对应,则在查找时只需查看在其对应存储位置有无包含所查关键字的记录即可。
我们称上述对应关系f为“哈希(Hash)函数”。按照这个思想建立的表为哈希表。
对于不同关键字可能得到相同的哈希地址,即key1!=key2,而f(key1)==f(key2),这种现象成为冲突(collision)。具有相同哈希值的关键字称为同义词(synonym)。在一般情况下,冲突只能尽可能的减少而不能完全避免(哈希函数是一个压缩映像)。因此在建造哈希表时,不仅要设定一个“好”的哈希函数,而且要设定一种处理冲突的办法。


哈希函数构造方法

1、直接定址法

取关键字或关键字的某个线性函数值作为哈希地址。即H(key)=key或者H(key)=a×key+b。
直接定址法所得的地址集与关键字集合大小相同,不同关键字不会产生冲突。

2、数字分析法

假设关键字都是事先知道的,则可取关键字的若干数位组成哈希地址。

3、平方取中法

取关键字平方后的中间几位作为哈希地址。一个数平方后的中间几位数和数的每一位都相关,由此随机分布的关键字得到的哈希地址也是随机的,取的位数由表长决定。

4、折叠法

将关键字分割成位数相同的几部分(最后一部分位数也可以不同),然后取这几部分的叠加和(舍去进位)作为哈希地址。
关键字位数很多,而且关键字的每一位上数字分布大致均匀时可以采用此法。

5、除留余数法

取关键字被某个不大于哈希表长m的数p除后所得余数为哈希地址。即H(key)=key MOD p,p<=m;
可以对关键字直接取模,也可以在折叠,平方运算之后取模。
但是,在使用此法时,对p的选择很重要。若p选的不好,容易产生同义词。
一般情况下,可以选p为质数或不包含小于20的质因子的合数。
6、随机数法
选择一个随机函数,取关键字的随机函数值作为它的哈希地址,即H(key)=Random(key)。通常,关键字长度不等时采用此法构造哈希函数较为恰当。


处理冲突的方法

1、开放定址法

Hi=(H(key)+di) MOD m,i=1,2,3,...,k(k<=m-1)
其中:H(key)为哈希函数;m为哈希表表长;di为增量序列有三种取法:di=1,2,3,...,m-1,称线性探测再散列;di=12,-12,22,-22,...,+-k2,(k<=m/2)称二次探测再散列;di=伪随机数序列,称伪随机探测再散列。

2、再哈希法

Hi=RH(key) i=1,2,3,...,k

3、链地址法

将所有关键字同义词存储在同一线性链表中。

4、建立公共溢出区

哈希表的查找及其分析

在哈希表上查找过程和建造哈希表过程基本一致。若查找位置上没有记录则查找不成功,否则比较关键字,若和给定值相等,则查找成功,否则根据建表时设定的处理冲突的方法找“下一地址”,直至哈希表某个位置为“空”或者表中所填记录关键字等于给定值时为止。

int hashsize[]={997,...}; //哈希表容量递增表,一个合适的素数序列。
typedef struct{
    ElemType *elem;
    int count;
    int sizeindex;
}HashTable;

\#define SUCCESS 1
\#define USUCCESS 0
\#define DUPLICATE -1
Status SearchHash(HashTable H,KeyType K,int &p,int &c){
    //若查找成功返回SUCCESS,p指示待查元素在表中的位置,否则返回UNSUCCESS,p指示插入位置。
    //c用来记录冲突次数

  p=Hash(K);
  while(H.elem[p].key!=NULLKEY&&!EQ(K,H.elem[p].key)
      collision(p,++c);
  if EQ(K,H.elem[p].key)
      return SUCCESS;
  else return UNSUCCESS;
}//SearchHash

Status InsertHash(HashTable &H,Elemtype e){
  c=0;
  if(SearchTable(H,e.key,p,c))
      return DUPLICATE;
  else if(c

由于冲突的产生,使得哈希表的查找过程仍然是一个给定值和关键字比较的过程。因此要以平局查找长度为衡量哈希表查找效率的度量。

在查找过程中需和关键字比较的个数取决于
1.哈希函数
2.处理冲突的方法
3.哈希表的装填因子

在线性探测再序列中易产生记录的二次聚集,即对于哈希地址不同的 关键字产生冲突;链地址法则不会产生类似情况。

装填因子越大表示哈希表的装满程度,装填因子越小,发生冲突的概率越小,平均查找长度越小。

哈希表的平均查找长度是装填因子的函数,而不是表长n的函数,可以选择一个合适的装填因子使平均查找长度限定在一个范围内。而对于非链地址处理冲突的哈希表中删除一个记录,需在该记录位置填一个特殊符号,以免找不到在它之后填入的同义词。

你可能感兴趣的:(数据结构与算法-哈希表)