如果key不是整数,设计散列函数:
例子题目:
如何将一个二维整点P的坐标映射为一个整数,使得整点P可以由该整数唯一地代表
假设一个整点P的坐标是(x,y),其中0<=x,y<=Range
那么可以令hash函数为H(P)=x*Range+y
这样对数据范围内的任意两个整点p1,p2,
H(p1)都不会等于H(p2)
就可以用H(P)来唯一地代表该整点P
接着可以通过证书hash的方法来进一步映射到较小的范围
字符串hash是将一个字符串S映射成一个整数,
使得该整数可以尽可能唯一地代表字符串S
先讨论(将字符串转换为唯一的整数)
int hashFunc(char S[],int len)
{
int id=0;
for(int i=0;i<len;i++)
{
id=id*26+(S[i]-'A');
}
return id;
}
显然,如果字符串S的长度比较长,那么转换成的整数也会很大
因此注意使用时len不能太长
如果出现了小写字母
可以将A~Z作为0~25,而把a~z作为26~51
int hashFunc(char S[],int len)
{
int id=0;
for(int i=0;i<len;i++)
{
if(S[i]>='A'&&S[i]<='Z')
id=id*52+(S[i]-'A');
else if(S[i]>='a'&&S[i]<='z')
id=id*52+(S[i]-'a')+26;
}
return id;
}
而如果出现了数字,一般有两种处理方法
①按照小写字母的处理方法,增大进制至62
②如果保证在字符串的末尾是确定个数的数字
那么就可以把前面英文字母的部分按上面的思路转换成整数
再将末尾的数字直接拼接上去
例如对由三个字符加一位数字组成的字符串“BCD4”来说
就可以先将前面的“BCD”转化为整数731
然后直接拼接上末尾的4变成7314即可
int hashFunc(char S[],int len)
{
int id=0;
for(int i=0;i<len;i++)
{
id=id*26+(S[i]-'A');
}
id=id*10+(S[len-1]-'0');
return id;
}
一个问题:
给出N个字符串(由恰好三位大写字母组成),再给出M个查询字符串
问每个查询字符串在N个字符串中出现的次数
#include<cstdio>
#define maxn 100
char S[maxn][5],temp[5];
int hashTable[26*26*26+10];
int hashFunc(char S[],int len)
{
int id=0;
for(int i=0;i<len;i++)
{
id=id*26+(S[i]-'A');
}
return id;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
{
scanf("%s",S[i]);
int id=hashFunc(S[i],3);
hashTable[id]++;
}
for(int i=0;i<m;i++)
{
scanf("%s",temp);
int id=hashFunc(temp,3);
printf("%d\n",hashTable[id]);
}
return 0;
}
知识点来自于《算法笔记》