散列定义与整数散列
给出N个数,问另外M个数是否在N个数中出现过?若用遍历的方法则时间复杂度太大( )不妨用空间换时间,设立一个bool型数组hashTable[10010],hashTable[x]==true表示某整数x在N个数中出现过,这样一开始读入N时就能进行处理,时间复杂度
#include<cstdio>
const int maxn = 100010;
int hashTable[maxn] = {0};
int main() {
int n, m, x;
scanf("%d%d", &n, &m);
for(int i = 0;i < n; i ++) {
scanf("%d", &x);
hashTable[x] = true; //数字x出现过
}
for(int i = 0;i < m; i++) {
scanf("%d", &x);
if(hashTable[x] == true){
printf("YES\n");
} else {
printf("NO\n");
}
}
return 0;
}
如果要求x出现的次数
#include<cstdio>
const int maxn = 100010;
int hashTable[maxn] = {0};
int main() {
int n, m, x;
scanf("%d%d", &n, &m);
for(int i = 0;i < n; i ++) {
scanf("%d", &x);
hashTable[x]++;
}
for(int i = 0; i < m; i++) {
scanf("%d", &x);
printf("%d\n", hashTable[x]);
}
return 0;
}
特点:直接把输入的数作为数组的下标
散列:通过函数把“元素”转化为整数,使得整数可以唯一地代表这个“元素”(比如把x变成数组下标)
除留余数法: ,表长TSize必须不小于mod。下文取TSize是一个素数,mod取与TSize相等。
解决两个key的H(key)值相同(即冲突)的办法:
(1)线性探查法:检查下一个位置(H(key)+1)是否被占,不断往下推
(2)平方探查法:检查下列位置
,
为正整数
(3)链地址法(拉链法):将所有H(key)相同的key连接成一条单链表(见7.3节)
字符串hash初步
字符串hash是指将一个字符串S映射为一个整数使之唯一表出S。
例:假设字符串均由大写字母A-Z构成,A-Z对应0-25,再将二十六进制转换为十进制
int hashFunc(char S[], int len) { //hash函数将字符串S转换为整数
int id = 0;
for(int i = 0; i < len; i++) {
id = id * 26+ (S[i] - 'A'); //将二十六进制转换为十进制
}
return id;
}
如果出现小写字母,把a-z作为26-51,变为五十二进制转换为十进制的问题,做法也是相同的
int hashFunc(char S[], int len) { //hash函数,将字符串S转换为整数
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;
如果出现了数字
(1)可以增大进制到62
(2)直接把数字拼上去,比如
int hashFunc(char S[], int len) { //hash函数,将字符串S转换为整数
int id = 0;
for(int i = 0; i < len - 1; i++) {
id = id * 26 + (S[i] - 'A');
}
id = id * 10 + (S[len - 1] - '0');
return id;
总结进制转换 id=id乘原进制位数+(S代表的长度-原进制首位字符)
问题:给出N个字符串(恰好由三位大写字母组成),再给出M个查询字符,求每个查询字符在N个字符串中出现的次数
#include<cstdio>
const int maxn = 100;
char S[maxn] [5], temp[5];
int hashTable[26 * 26 * 26 +10];
int hashFunc(char S[], int len) { //hash函数,将字符串S转换为整数
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); //将字符串S[i]转换为整数
hashTable[id]++; //该字符串的出现次数加1
}
for(int i = 0; i < m; i++) {
scanf("%s", temp);
int id = hashFunc(temp, 3); //将字符串temp转换为整数
printf("%d\n", hashTable[id]); //输出该字符串的出现次数