哈希表的学习

定义

在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使每个关键字和结构中一个惟一的存储位置相对应。
在此, 我们称这个对应关系f为哈希(Hash)函数,按这个思想建立的表为哈希表。

哈希表特点

(1) 哈希函数是一个映像,因此哈希函数的设定很灵活,只要使得任何关键字由此所得的哈希函数值都落在表长允许范围之内即可;
(2) 对不同的关键字可能得到同一哈希地址

改进方向

在一般情况下,哈希函数是一个压缩映像,这就不可避免产生冲突。因此,在建造哈希表时不仅要设定一个“好”的哈希函数,而且要设定一种处理冲突的方法。

冲突

对不同的关键字可能得到同一哈希地址,即key1≠key2, 而f(key1 ) = f(key2),这种现象称冲突(collision )。

构造哈希函数的方法

1.直接定址法

取关键字或关键字的某个线性函数值为哈希地址。即:
H(key)=key或H(key)=a• key+b

缺点:

由于直接定址所得地址集合和关键字集合的大小相同。因此,对千不同的关键字不会发生冲突。但实际中能使用这种哈希函数的情况很少。

2. 数字分析法

假设关键字是以r为基的数( 如: 以10为基的十进制数),并且哈希表中可能出现的关键字都是事先知道的,则可取关键字的若干数位组成哈希地址。

3. 平方取中法

取关键字平方后的中间几位为哈希地址。

4 .折叠法

将关键字分割成位数相同的几部分(最后一部分的位数可以不同), 然后取这几部分的叠加和(舍去进位)作为哈希地址,这方法称为折叠(folding)。

5. 除留余数法

取关键字被某个不大于哈希表表长m的数p除后所得余数为哈希地址。即
H(key) = key MOD p, p≤m

6. 随机数法

选择一个随机函数,取关键字的随机函数值为它的哈希地址, 即H (key) = random(key),其中random为随机函数。通常,当关键字长度不等时采用此法构造哈希函数较恰当。
当。

实际工作考虑的因素有:

(1) 计算哈希函数所需时间(包括硬件指令的因素);
(2) 关键字的长度;
(3) 哈希表的大小;
(4) 关键字的分布情况;
(5) 记录的查找频率。

处理冲突的方法

1.开放定址法

将冲突的数依次存入冲突位置的物理上联系的下一个位置。

2.再哈希法

3. 链地址法

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

4. 建立一个公共溢出区

哈希表的查找

Status SearchHash(HashTable H, HKeyType K, int &p, int &c) {  
   // 算法9.17
   // 在开放定址哈希表H中查找关键码为K的元素,
   // 若查找成功,以p指示待查数据元素在表中位置,并返回SUCCESS;
   // 否则,以p指示插入位置,并返回UNSUCCESS,
   // c用以计冲突次数,其初值置零,供建表插入时参考
   p = Hash(K);                          // 求得哈希地址
   while ((H.elem[p].key != NULLKEY) &&  // 该位置中填有记录
          !equal(K, (H.elem[p].key)))   // 并且关键字不相等
      collision(p, ++c);                 // 求得下一探查地址p
   if (equal(K, (H.elem[p].key)))
      return SUCCESS;        // 查找成功,p返回待查数据元素位置
   else return UNSUCCESS;    // 查找不成功(H.elem[p].key == NULLKEY),
                             // p返回的是插入位置
} // SearchHash
Status InsertHash(HashTable &H, HElemType e) {  // 算法9.18
   // 查找不成功时插入数据元素e到开放定址哈希表H中,并返回OK;
   // 若冲突次数过大,则重建哈希表
   int c = 0;
   int p = 0;
   if (SearchHash(H, e.key, p, c) == SUCCESS )
      return DUPLICATE;        // 表中已有与e有相同关键字的元素
   else if (c < H.cursize) {   // 冲突次数c未达到上限,(阀值c可调)
      H.elem[p] = e;  ++H.count;  return SUCCESS;  // 插入e
   } else {
      RecreateHashTable(H);  // 重建哈希表
      return UNSUCCESS;
   } 
} // InsertHash

(1) 虽然哈希表在关键字与记录的存储位置之间建立了直接映像, 但由于“冲突"的产生,使得哈希表的查找过程仍然是一个给定值和关键字进行比较的过程。因此,仍需以平均查找长度作为衡扯哈希表的查找效率的量度。
(2) 查找过程中需和给定值进行比较的关键字的个数取决于下列三个因素: 哈希函数,处理冲突的方法和哈希表的装填因子。

哈希表的装填因子定义为

在这里插入图片描述

uthash:C语言中优秀的哈希函数库

uthash

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值