算法笔记学习Part3:入门篇 2 散列(例题待更新)

散列的定义与整数散列

散列的定义

——将元素通过一个函数转换为整数,使得该整数可以尽量唯一的代表这个元素
在这个过程中,这个转换函数称为散列函数H,原始元素记为key,那么转换后的整数就是H(key)

常用散列函数

对于key是整数的情况,常用的方法有直接定址法,平方取中法和除留余数法,其使用如下:

  1. 直接定址法
1.H(key) = key			//恒等变换
2.H(key) = a * key + b;	//线性变换
  1. 平方取中法(待补充)
  2. 除留余数法
H(key) = key % mod;

关于除留余数法

通过除留余数法的散列函数,我们可以将很大的数转换为不超过mod的整数,这样在key很大时H(key)也可以作为可行的数组下标(表长TSize要不小于mod,不然会越界)
当mod时一个素数时,H(key)能够尽可能的覆盖[0,mod)范围内的每一个数
冲突的解决:

  1. 线性探查法
  2. 平方探查法
  3. 链地址法

通常可以使用标准模板库中的map来直接使用hash的功能

字符串hash初步

基本思路:将字符串通过进制转换的方式转换为整数

  • 若仅包含大写字母,则考虑从26进制转换为10进制
int hashFunc(char S[],int len) {			//hash函数,将字符串扎转换为整数 
	int id = 0;
	for (int i = 0; i < len; i++) {
			id = id * 26 + (S[i] - 'A');
	}
	return id;
}
  • 若包含大写字母和小写字母,考虑由52进制转换10进制
int hashFunc(char S[],int len) {			//hash函数,将字符串扎转换为整数 
	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;②若保证在字符串末尾是确定位数的数字,则可以前面的字符照例转换,后面的数字之后拼接上去

例题

题目描述

给出N个恰好由3位大写字母组成的字符串,再给出m个查询字符串,问每个查询字符串在n个字符串中出现的次数

解决方案
#include

const int maxn = 100;
char S[maxn][5], temp[5];//定义二维数组S存储N个字符串,一维数组temp存储欲查询字符串 
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++)//输入n个字符串并存放到二维数组 S中 ,并将其对应的整数作为下标,找到hashTable对应位置加一 
	{
		scanf("%s",&S[i]);
		int id = HashFunc(S[i], 3);
		hashTable[id]++;
	}
	for (int i = 0; i < m; i++)//输入m个查询字符串,并找到hashTable中对应整数坐标内记录的字符串出现次数 
	{
		scanf("%s",&temp);
		int id = HashFunc(temp,3);
		printf("%d",hashTable[id]);
	}
	
	return 0;
	
}

你可能感兴趣的:(算法学习)