数据结构之散列表

散列表(哈希表)

“散列(Hashing)”的基本思想是(1) 以关键字key为自变量,通过一个确定的函数 h(散列函数),计算出对应的函数值h(key),作为数据对象的存储地址。(2)可能不同的关键字会映射到同一个散列地址上,即h(keyi) = h(keyj)(当keyi ≠keyj),称为“冲突(Collision)”。—-需要某种冲突解决策略


散列函数的构造方法

一个“好”的散列函数一般应考虑下列两个因素:

  1. 计算简单,以便提高转换速度;
  2. 关键词对应的地址空间分布均匀,以尽量减少冲突。

数字关键词的散列构造函数

  1. 直接定址法 取关键词的某个线性函数值为散列地址,即h(key) = a*key + b (a、 b为常数)

  2. 除留余数法 散列函数为: h(key) = key mod p 这里,p=Tablesize,一般p取素数.

  3. 数字分析法 分析数字关键字在各位上的变化情况,取比较随机的位作为散列地址。
    比如: 取11位手机号码key的后4位作为地址:
    散列函数为:h(key) = atoi(key+7) (char * key) hash1

  4. 折叠法 把关键词分割成位数相同的几个部分,然后叠加
    如: 56793542
    hash2

  5. 平方取中法 hash3

字符串关键字的散列函数构造

  1. ASCII码加和法
    h(key)=$(\sum key[i])$ mod TableSize
    问题:冲突严重

  2. 前3个字符移位法 h(key)=(key[0]*27^2+key[1]*27+key[2]) mod TableSize

  3. 移位法 涉及关键词所有n个字符,并且分布得很好: $h(key)=(\sum_{i=0}^{n-1}key[n-i-1]\times32^i ) $ mod TableSize 如何快速计算: h("abcde")='a'*32^4+'b'*32^3+'c'*32^2+'d'*32+'e'

代码:

Index Hash ( const char *Key, int TableSize )
{
	unsigned int h = 0; /* 散列函数值, 初始化为0 */
	while ( *Key != ‘\0’) /* 位移映射 */
	h = ( h << 5 ) + *Key++;
	return h % TableSize;
}

冲突处理方法

常用处理冲突的思路:

  • 换个位置: 开放地址法
  • 同一个位置的冲突对象组织在一起: 链地址法

    开放定址法

    一旦产生了冲突(该地址已有其它元素),就按某 种规则去寻找另一空地址.

  • 若发生了第 i 次冲突,试探的下一个地址将增加di, 基本公式是:hi(key) = (h(key)+di) mod TableSize ( 1≤ i < TableSize )
  • $d_i$决定了不同的解决冲突方案: 线性探测($d_i=i$)、平方探测($d_i=\pm i^2$)、双散列($d_i=i \times h_2\left(key\right)$)。
线性探测法(Linear Probing)
  • 线性探测法: 以增量序列 1, 2, ……,(TableSize -1)循环试探下一个存储地址。例4
平方探测法(Quadratic Probing)-二次探测
  • 平方探测法: 以增量序列$1^2, -1^2, 2^2, -2^2, ……, q^2, -q^2$且q ≤ |TableSize/2| 循环试探下一个存储地址。hash5
  • 是否有空间,平方探测(二次探测)就能找得到?hash6

    有定理显示:如果散列表长度TableSize是某个4k+3(k是正整数)形式的素数时, 平方探测法就可以探查到整个散列表空间。

  • 在开放地址散列表中, 删除操作要很小心。通常只能“懒惰删除” ,即需要增加一个“删除标记(Deleted)” ,而并不是真正删除它。以便查找时不会“断链”。其空间可以在下次插入时重用。
双散列探测法(Double)

双散列探测法: $d_i$ 为$i*h_2(key)$, $h_2(key)$是另一个散列函数。探测序列成: $h_2(key), 2h_2(key), 3h_2(key)$, ……对任意的key, $h_2(key) ≠ 0 !$探测序列还应该保证所有的散列存储单元都应该能够被探测到。选择以下形式有良好的效果:$h_2(key) = p - (key mod p)$其中: p < TableSize, p、 TableSize都是素数。

再散列

当散列表元素太多(即装填因子 α太大)时, 查找效率会下降;实用最大装填因子一般取 0.5 <= α<= 0.85当装填因子过大时,解决的方法是加倍扩大散列表,这个过程叫做“再散列(Rehashing)”

分离链接法

将相应位置上冲突的所有关键词存储在同一个单链表中

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值