《算法笔记》第4章 入门篇(2)—算法初步 4.2散列(C/C++)

《算法笔记》第4章 入门篇(2)—算法初步

4.2散列

4.2.1散列的定义与整数散列

1.O_O
给出N个正整数,再给出M个正整数,问这M个数中的每个数分别是否在N个数中出现过,其中N,M<=10^5,且所有
正整数均不超过10^5。例如N=5,M=3,N个正整数为{8,3,7,6,2},欲查询的M个正整数为{7,4,2},于是后者中
只有72在N个正整数中出现过,而4是没有出现过的。
代码如下:
//用空间换时间
#include<cstdio>
using namespace std;
//因为N<=10^5=100000,所以maxn可以为100010 
const int maxn = 100010;//maxn表示数组的长度
//数组hashTable用于记录欲查询数x是否出现过 
bool hashTable[maxn] = {false};//默认N个正整数均未出现过 
int main(){
	int n;//n表示N个正整数 
	int m;//m表示M个正整数 
	int x;//x表示欲查询数
	scanf("%d %d", &n, &m);//输入n和m 
	//通过循环输入N个正整数 
	for(int i = 0; i < n; i++){
		scanf("%d", &x);//输入x
		hashTable[x] = true;//表示欲查询数x出现过 
	}
	//通过循环输入M个正整数
	for(int j = 0; j < m; j++){
		scanf("%d", &x);//输入x
		//判断欲查询数x是否已经出现过 
		if(hashTable[x] == true){//x出现过 
			printf("%d在N个正整数中出现过\n", x);
		}else{//x未出现过 
			printf("%d在N个正整数中未出现过\n", x);
		}
	} 
	return 0;
} 
运行结果如下:

在这里插入图片描述

2.O_O
将上一题的要求改为:
求M个欲查询的数中每个数在N个数中出现的次数,其他条件不变。
代码如下:
#include<cstdio>
using namespace std;
//因为N<=10^5=100000,所以maxn可以为100010 
const int maxn = 100010;//maxn表示数组的长度
//数组hashTable用于记录欲查询数x出现的次数 
int hashTable[maxn] = {0};//默认N个正整数出现次数均为0 
int main(){
	int n;//n表示N个正整数 
	int m;//m表示M个正整数 
	int x;//x表示欲查询数
	scanf("%d %d", &n, &m);//输入n和m 
	//通过循环输入N个正整数 
	for(int i = 0; i < n; i++){
		scanf("%d", &x);//输入x
		hashTable[x]++;//表示欲查询数x的出现次数自增1 
	}
	//通过循环输入M个正整数
	for(int j = 0; j < m; j++){
		scanf("%d", &x);//输入x
		//输出正整数x在N个正整数中的出现次数 
		printf("%d的出现次数为:%d\n", x, hashTable[x]);
	} 
	return 0;
} 
运行结果如下:

在这里插入图片描述

4.2.2字符串hash初步

给出N个字符串(由恰好三位大写字母组成),再给出M个查询字符串,
问每个查询字符串在N个字符串中出现的次数。
代码如下:
#include<cstdio>
using namespace std;
const int maxn = 100;//maxn表示存储N个字符串的数组的一维长度
//数组S用于存储输入的N个字符串;
//数组temp用于存储输入的M个字符串中的单个字符串。 
//因为题目要求字符串恰好由三位大写字母组成,所以数组S的二维
//长度和数组temp的一维长度均可为5。 
char S[maxn][5], temp[5];
//因为字符串恰好由三位大写字母组成,即len=3,且字符串能够映射
//的最大整数为26^len-1,即26^3-1,所以数组hashTable的长度可以为26*26*26+10 
int hashTable[26*26*26+10];
//函数hashFunc用于将字符串映射为十进制整数 
int hashFunc(char S[], int len){
	int id = 0;
	//通过循环实现将字符串映射的二十六进制整数转换为十进制整数 
	for(int i = 0; i < len; i++){
		//操作(S[i]-'A')可将单个字符映射为[0,25]范围内的唯一二十六进制整数 
		id = id*26 + (S[i] - 'A');
	}
	return id;
}
int main(){
	int n, m;//n的范围为:n<=100 
	scanf("%d %d", &n, &m);//输入n和m
	//通过循环输入N个字符串 
	for(int i = 0; i < n; i++){
		scanf("%s", S[i]);//输入单个字符串
		int id = hashFunc(S[i], 3);//将输入的字符串映射为十进制整数并赋值给id
		hashTable[id]++;//输入的字符串出现的次数自增1 
	}
	//通过循环输入M个查询字符串 
	for(int i = 0; i < m; i++){
		scanf("%s", temp);//输入单个字符串
		int id = hashFunc(temp, 3);将输入的查询字符串映射为十进制整数并赋值给id
		//输出该查询字符串在N个字符串中出现的次数 
		printf("%s的出现次数为:%d\n", temp, hashTable[id]);
	}
	return 0;
}
运行结果如下:

在这里插入图片描述

参考资料如下:

[1] 胡凡,曾磊.算法笔记[M].北京:机械工业出版社,2022:85-98.
[2] codeup网址:http://codeup.hustoj.com
[3] PAT网址:https://www.patest.cn/practice

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值