散列函数的构造方法

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

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

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

1.1 直接定址法

取关键词的某个线性函数值为散列地址,即
h(key) = a × key + b (a、b为常数)

地址 h(key)出生年月(key人数(attribute)
019001285万
119011281万
219021280万
………………
1020001250万
………………
1020111180万

根据上表,得出散列函数的构造函数为:h(key)=key-1990

1.2 除留余数法

散列函数为:h(key) = key mod p
例: h(key) = key % 17

地址012345678910111213141516
关键词34182202374227113015

一般,p 取素数,这里:p = Tablesize = 17

1.3 数字分析法

分析数字关键字在各位上的变化情况,取比较随机的位作为散列地址
比如:取11位手机号码key的后4位作为地址:
散列函数为:h(key) = atoi(key+7) (char *key)
在这里插入图片描述

如果关键词 key是18位的身份证号码:
在这里插入图片描述
用红线标出来的是变化比较大的的6位数字,这里就取这6位数字来组建散列函数
h1(key) = (key[6]-‘0’)×104 + (key[10]-‘0’)×103 +(key[14]-‘0’)×102 + (key[16]-‘0’)×10 + (key[17]-‘0’)

当 key[18] = ‘x’时,身份证最后一位为X
h(key) = h1(key)×10 + 10

当 key[18] 为’0’~’9’时,身份证最后一位为数字
h(key) = h1(key)×10 + key[18]-‘0’

1.4 折叠法

把关键词分割成位数相同的几个部分,然后叠加
在这里插入图片描述

1.5 平方取中法

在这里插入图片描述

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

2.1 一个简单的散列函数——ASCII码加和法

对字符型关键词key定义散列函数如下:
h(key) = ( Σkey[i] ) mod TableSize

问题:对于ASCII之和相同的字符串就会冲突,比如a3、 b2、c1;eat、 tea;

2.2 简单的改进——前3个字符移位法

把字符串的前三个字符取出来,看成27进制种的个位数,十位数,百位数,为什么使用27,因为有26个字符,考录空格,就是27。
h(key)=(key[0]×272 + key[1]×27 + key[2]) mod TableSize

问题:
1、仍然冲突:string、 street、strong、structure等等,前三个字符相同;

2、空间浪费:3000/263 ≈ 30%
前三个字符的不同组合在实际使用中大概有3000种可能,我们假设所有的字母(26个英文字母)排列组合有263种情况,散列表只用到30%。

2.3 好的散列函数——移位法

涉及关键词所有n个字符,并且分布得很好:
这里就考虑这个字符串的所有位。把它看成是32进制数的每一位,为什么是32进制,后面会说。
在这里插入图片描述
如何快速计算:
h(“abcde”)=‘a’*324+’b’*323+’c’*322+’d’*32+’e’

计算过程如下:
h = a
h = a * 32 + b
h = (a * 32 +b) * 32 + c
h = ((a * 32 + b) * 32 + c) * 32 + d
h = (((a * 32 + b) * 32 + c) * 32 + d) * 32 + e
h = h%TableSize
这里a * 32 == a<<5,左移5位相当于乘以32

快速计算代码如下:

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

3 总结

  • 数字关键词的散列函数构造(1、直接定址法 2、除留余数法 3、数字分析法 4、折叠法 5、平方取中法)
  • 字符关键词的散列函数构造(1、ASCII码加和法 2、前3个字符移位法 3、移位法)
  • 14
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值