【pta】7-42 整型关键字的散列映射<数字类型散列表除留余数法、线性探查法>

一、题目大意

题目链接:https://pintia.cn/problem-sets/15/problems/889

7-42 整型关键字的散列映射 (25 分)
 

给定一系列整型关键字和素数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

posted @ 2021-09-01 11:13  北辰ฅ  阅读(512)  评论(0)    收藏  举报