散列的介绍
散列(hash)是常用的算法思想之一,在很多程序上都会有意无意的使用到。用一句话来概括散列思想的话就是:“将元素通过一个函数转换为整数,使得该整数可以尽量唯一地代表这个元素”。其中把转换函数称为散列函数H。
那么对key是整数来说,有哪些常用的散列函数呢?一般来说,常见的散列函数有直接定址法、平方取中法、除留余数法,其中直接定址法是指恒等变换(即H(key)=key,很多问题都是直接把key作为数组下标,是最常见最实用的散列应用)。
散列的适用情形
那么,什么情况下使用散列思想呢?如何在竞赛或者考试中联想到散列思想呢?
- 在使用散列思想时,题目一般会给出两个字符串或者两个数组,这两个字符串或者的元素之间存在ans=S1-S2的类似关系;
- 题目用于其中某个字符串查询另一个字符串中的元素的情形;
散列的运用
下面给出一些散列思想的运用。
【PAT】B1039
#include <stdio.h>
#include <string.h>
int main(){
char hashTable[1010]={0};
char str1[1010],str2[1010];
int sum=0;
gets(str1);
gets(str2);
int len_a=strlen(str1);
int len_b=strlen(str2);
for(int i=0;i<len_a;i++){ //数组的下标是珠子颜色的代表字符,统计每种颜色各有多少个珠子
hashTable[str1[i]]++;
}
for(int i=0;i<len_b;i++){ //统计完毕后,将需要得到的珠子减去原有的珠子,若出现负数,则表 示某种颜色的珠子少于需求
hashTable[str2[i]]--;
}
for(int i=0;i<len_b;i++){
if(hashTable[str2[i]]<0){
sum=sum+hashTable[str2[i]];
hashTable[str2[i]]=0;
}
}
if(sum<0) printf("No %d",0-sum);
else printf("Yes %d",len_a-len_b);
return 0;
}
【PAT】B1042
#include <stdio.h>
#include <string.h>
int main(){
int HashTable[256]={0};
int k=0,len;
char str[1010],j;
gets(str);
len=strlen(str);
for(int i=0;i<len;i++){
if(str[i]>='A'&&str[i]<='Z'){
HashTable[str[i]-'A']++; //将标记字符转化为唯一字符表示,这适用于字符串中给出大小写,但实际不需要区分大小写的情况
}
else if(str[i]>='a'&&str[i]<='z'){
HashTable[str[i]-'a']++;
}
else
HashTable[str[i]]=0;
}
for(int i=0;i<26;i++){
if(HashTable[i]>HashTable[k]){
k=i;
}
}
printf("%c %d\n",'a'+k,HashTable[k]);
return 0;
}
【PAT】A1048
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
int main(){
int n,m,a;
int hashtable[1005]={0};
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
scanf("%d",&a);
++hashtable[a]; //将输入的数字作为数组的下标存储起来,把数组+下标的组合来存放该下标(即数字)的个数
}
for(int i=1;i<m;i++){
if(hashtable[i]&&hashtable[m-i]){
if(i==m-i&&hashtable[i]<=1){
continue;
}
printf("%d %d\n",i,m-i);
return 0;
}
}
printf("No Solution\n");
return 0;
}
综 述
使用散列表示的方式一般有:
- 以数组的下标作为记录该数字的存在与否(通过int hashtable[maxn]={0}或者bool hashtable[maxn]={false});
- 以数组的下标作为改为字符记录;
- 以数组的下标和数组本身结合,记录下标(即数字或者字符)出现的次数(如hashtable[3]=2,hashtable['P']=3分别表示3出现了2次,字符P出现了3次)。
看到题目后应结合题目具体分析寻找最简单的解法。