散列查找

散列函数的构造方法

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

  1. 直接定址法
h(key) = a * key + b;	//a, b为常数
int h(int key)
{
	int a = 1, b = 2;
	return a * key + b;
}

这类函数计算简单,分布均匀,不会产生冲突,但要求地址集合与关键字集合大小相同,因此,对于较大的关键词集合不适用。所以在现实中并不常用

  1. 除留余数法
    假设散列表长度为TableSize,选取一个正整数p <= TableSize
h(key) = key mod p;
int h(int key, int p)
{
	return key % p;
}

注意到,如果p < TableSize,则意味着地址p ~ TableSize - 1是不能通过散列表直接映射到的。不过不用担心空间浪费,在冲突发生时就会用到它们

  1. 数字分析法
    如果数字关键词的位数比较多,在特定的情况下,有些位数易相同,而有些位数比较随机。比如11位手机号码,前3位容易相同,中间4位表示用户归属地,在一定范围内也容易重复,而最后4位是很随机的。所以只选择后4位作为散列地址,采用字符串存储号码,C语言中的字符串转换成整数处理函数atoi,于是散列函数表示为:
h(key) = atoi(key + 7) mod p;	//如果4位数还是太大了, 再用一次取模

这里key + 7表示指针往后移7个数字,即留下4位数字

int h(char key[], int p)
{
	return atoi(key + 7) % p;
}

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

  1. 一个简单的散列函数——ASCII码加和法
h(key) = (∑key[i]) mod TableSize;

显然冲突可能非常严重,比如a3, b2, c1的散列值都是100;关键词"tea"和"eat"也是冲突的

  1. 简单的改进——前3个字符移位法
h(key) = (key[0] + key[1] * 27 + key[0] * 27^2) mod MaxSize;

选择27进制是因为26个字母和一个字符空格,该散列函数只考虑前3个字符,当散列表太大时,这个函数还是不合适的

  1. 好的散列函数——移位法
    这个散列函数涉及关键词的所有n个字符,并且分布的很好
    在这里插入图片描述
    该函数用于处理长度为n的字符串关键词,每位字符占5位(即2^5 = 32)。具体实现时并不需要做乘法运算,而是通过一次左移5位来完成,这也是为什么选用32来代替27的原因
int h(const char *key, int TableSize)
{
	int h = 0;
	while(*key != '\0')
		h = (h << 5) + *key++;
	
	return h % TableSize;
}

该函数遇到的主要问题是,当n太大时,前面若干位字符可能被左移出界,而起作用的只有最后几位字符。一种解约的办法是不使用整个字符串,而是从中选择若干位有代表性的字符进行映射,比如字符串长度大于12的时候,仅选取奇数位置上的字符来实现散列函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值