【pta】7-42 整型关键字的散列映射<数字类型散列表除留余数法、线性探查法>
一、题目大意
题目链接:https://pintia.cn/problem-sets/15/problems/889
给定一系列整型关键字和素数P,用除留余数法定义的散列函数H(Key)=Key将关键字映射到长度为P的散列表中。用线性探测法解决冲突。
输入格式:
输入第一行首先给出两个正整数N(≤1000)和P(≥N的最小素数),分别为待插入的关键字总数、以及散列表的长度。第二行给出N个整型关键字。数字间以空格分隔。
输出格式:
在一行内输出每个整型关键字在散列表中的位置。数字间以空格分隔,但行末尾不得有多余空格。
输入样例:
4 5
24 15 61 88
输出样例:
4 0 1 3
二、第一版代码
#include <bits/stdc++.h> using namespace std; const int inf=0x3f3f3f3f; int main(void) { int a[10005]; memset(a,inf,sizeof(a)); int n,prime,temp; scanf("%d %d",&n,&prime); for (int i=0;i<n;i++) { scanf("%d",&temp); int cnt=temp%prime; while (a[cnt]!=inf&&a[cnt]!=temp) cnt++; a[cnt]=temp; if (i>0) printf(" "); printf("%d",cnt); } return 0; }
看到这道题后去网上搜了一下有关散列表数据结构的内容,并大致了解了除留余数法、线性探查法。
但是一直有两个点过不去

卡了一个多小时后再去看了一遍数据结构的课,发现了问题所在
int cnt=temp%prime; while (a[cnt]!=inf&&a[cnt]!=temp) cnt++;
我原本以为,如果要插入的数所对应的哈希值数组内已经有值的话,就无脑在哈希值之后一个一个往后找直到找到一个空着的位置插入

实际上可以理解为哈希值每次增加后取余,直到对应的数组里是空的就插入
三、ac代码
#include <bits/stdc++.h> using namespace std; int a[10005]; int main(void) { int n,p,temp; scanf("%d %d",&n,&p); for (int i=0;i<n;i++) { scanf("%d",&temp); int cnt=0; while (a[(temp+cnt)%p]&&a[(temp+cnt)%p]!=temp) cnt++; a[(temp+cnt)%p]=temp; if (i>0) printf(" "); printf("%d",(temp+cnt)%p); } return 0; }

同时对代码进行了优化,比如将a数组定义为全局数组,默认值就是0
还学会了一种新的修改格式的方法:
if (i>0) printf(" ");
四、亿些知识点
哈希表(散列表)
将空间换时间,查找效率高,平均复杂度为O(1)
数字类型散列表的常用求哈希值的方法:除留余数法
设散列表中允许的地址数为m,取一个不大于m,但最接近或者等于m的质数,按照哈希函数:Hash( key ) = key % p ( p <= m) ,将关键码转换成哈希地址。
当散列表中的元素产生冲突时,就需要一种散列冲突处理方法,这里介绍一种:线性探查法
这里借用https://blog.csdn.net/lz201788/article/details/79735508的图

本质不太难,只需要注意一下代码的实现方式即可(经典踩坑)

参考了很多大佬写的文章,再次感谢
peace

浙公网安备 33010602011771号