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

4.2.1 散列的定义与整数散列

1.散列的引入:

在这里插入图片描述

2.散列的概念:

1. 在N个数中,查询M个数是否存在

在这里插入图片描述

#include<iostream>
using namespace std;
const maxn=100010;
bool v[maxn]={false};
int main()
{
	int n,m;
	cin >> n >> m;
	for(int i=0; i<n; i++)
	{
		int temp;
		cin >> temp;
		v[temp]=true;
	}
	for(int i=0; i<m; i++)
	{
		if(v[i]==true)
			cout << "存在" << endl;
		else 
			cout << "不存在" << endl;
	}
	return 0;
}

时间复杂度为:o(m+n)


2. 查询m个数中,在n中出现的次数:

在这里插入图片描述

#include<iostream>
using namespace std;
const maxn=100010;
int v[maxn]=0;
int main()
{
	int n,m;
	cin >> n >> m;
	for(int i=0; i<n; i++)
	{
		int temp;
		cin >> temp;
		v[temp]++;
	}
	for(int i=0; i<m; i++)
	{
		int temp1;
		cin >> temp1;
		cout << temp1 << " " << v[temp1] << endl;
	}
	return 0;
}

时间复杂度为:o(m+n)


3. 散列的定义:

在这里插入图片描述

4. 常用的散列函数:

1. 直接定址法:

直接把key作为数组下标,是最常见最实用的散列应用或者是线性变换(H(key)=a*key+b)

2. 除留余数法

在这里插入图片描述
通过散列函数,可以把很大的数转化为不超过mod的整数,这样就可以将他作为可行的数组下标(注意,表长TSize必须不小于mod,不然会产生越界)

当mod是一个素数时,H(key)能尽可能覆盖[0,mod]范围内的每一个数。一般为了方便起见,取TSize是一个素数,而mod直接取成与TSize相等


5. 冲突:

1. 冲突原因:

在这里插入图片描述

2. 解决冲突的三种办法:
1.1 线性探查发(Linear Probing)

在这里插入图片描述

2. 平方探查法:(Quadratic probing)

在这里插入图片描述

3. 链地址法:(拉链法:)

在这里插入图片描述



4.2.2 字符串hash初步:

1.前言:

在这里插入图片描述

2.将大写字母A~Z转化为26进制:

在这里插入图片描述

int HashFunc(char S[], int len)
{
	int id=0;
	for(int i=0; i<len; i++)
		id=26*i+S[i]-'A';
	return id;
}

3.将大写字母A~Z和小写字母a ~z转化为52进制

在这里插入图片描述

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;
}

3.出现大写字母,小写字母,数字有两种方式处理方式:

3.1 按照小写字母的处理方法,增大进制数至62

在这里插入图片描述

int HashFunc(char S[],int len)
{
	int id=0;
	for(int id=0; id<len; id++)
	{
		if('A'<=s[i] && s[i]<='Z')
			id=id*62+s[i]-'A';
		else if('a'<=s[i] && s[i]<='z')
			id=id*62+s[i]-'a'+26;
		else if('0'<=s[i] && s[i]<='9')
			id=id*62+s[i]-'0'+52;
	}
}
3.2 如果保证在字符串的末尾是确定个数的数字,那么就可以把前面英文字母组成的字符串按照之前的思路转化为整数,再将末尾的数字直接拼上去

在这里插入图片描述

int HashFunc(char S[],int len)
{
	int id=0;
	for(int i=0; i<len-1; i++)
		id=id*26+S[i]-'A';
	id=id*10+S[len-1]-'0';
}

4.以一个问题结尾:

在这里插入图片描述

#include<iostream>
using namespace std;
const int maxn=100;
int HashTable[26*26*26+10]={0};
char S[maxn][5],temp[5];         //S[][]设置成2维数组,每一行表示1个字符串
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;
    cin >> n >> m;
    for(int i=0; i<n; i++)
    {
        cin >> S[i];
        int kb=HashFunc(S[i],3);
        HashTable[kb]++;
    }
    for(int i=0; i<m; i++)
    {
        cin >> temp;
        int kb1=HashFunc(temp,3);
        cout << HashTable[kb1] << endl;

    }
}



4.3递归:

4.3.1 分治:

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值