AcWing 840. 模拟散列表

原题链接如下:
840. 模拟散列表 - AcWing题库

第一种方式:拉链法

映射之后为同一个数字的全部存在同一个h[K]下面,像一条拉链,这其实也就是我们数组和之前数组模拟单链表的组合

这里的h[k]在拉链里的作用就相当于之前的单链表的头结点

在这里插入图片描述

//先采用拉链法
#include<cstring>
#include<iostream>
using namespace std;

//我们哈希表的存储应尽可能采用质数
//因此这里我们需要找一个比比100000大的最小质数
/*int main()
{
    for(int i = 100000;;i++)
    {
        bool flag = true;
        for(int j = 2;j*j<i;j++)
        {
            if(i%j==0)
            {
                flag = false;
                break;
            }
        }
        if(flag)
        {
            cout<<i;
            break;
        }
    }
    return 0;
}
输出结果是:100003
*/
const int N = 100003;

int h[N],e[N],ne[N],idx;
void insert(int x)
{
    int k = (x%N+N)%N;//先进行映射
    e[idx] = x;
    ne[idx] = h[k];
    h[k] = idx++;
}
bool find(int x)
{
    int k = (x%N+N)%N;
    for(int i = h[k];i!=-1;i = ne[i])
    {
        if(e[i] == x)
            return true;
    }
    return false;
}
int main()
{
    int n;
    cin>>n;
    //先把h[N]中所有元素都先指向空(也就是我们规定的-1)
    memset(h,-1,sizeof h);
    while(n--)
    {
        char op[2];
        int x;
        scanf("%s%d",op,&x);
        if(*op == 'Q')
        {
            if(find(x)) puts("Yes");//
            else puts("No");
        }
        else insert(x);
    }
    return 0;
}

第二种方法:开放寻址法

在这里插入图片描述

//采用开放寻址法
#include<cstring>
#include<iostream>
using namespace std;

//我们哈希表的存储应尽可能采用质数
//因此这里我们需要找一个比比200000大的最小质数
/*int main()
{
    for(int i = 200000;;i++)
    {
        bool flag = true;
        for(int j = 2;j*j<i;j++)
        {
            if(i%j==0)
            {
                flag = false;
                break;
            }
        }
        if(flag)
        {
            cout<<i;
            break;
        }
    }
    return 0;
}
输出结果为:200003
*/
const int N = 200003,null = 0x3f3f3f3f;
//相对于拉链法的优势就是只需要一个数组
int h[N];
//核心操作就是这个find函数
/*find函数的作用是,如果映射的k对应的h[k]上没有的别的元素占领(包括自己)
就return k,此时表示我应该插入的k值
*/
/*
如果映射的k对应的h[k]上就是x自己,则此时return k的意义就是获取x在h[]数组中的位置
*/
/*
如果映射的k对应的h[k]上占领的不是自己,并且h[k]不是空的
表明此时是其他人已经占领了k,所以我们需要找下一个坑
所以k++一直往下找,知道找到合适的
*/
int find(int x)
{
    int k = (x%N+N)%N;
    while(h[k]!=null&&h[k]!=x)
    {
        k++;
        if(k==N)k = 0;
    }
    
    return k;
}
int main()
{
    int n;
    cin>>n;
    //先把h[N]中所有元素都先指向0x3f(h中是int,四个字节,组合起来的ox3f3f3f3f就是我们定义的无穷值null)
    memset(h,0x3f,sizeof h);
    while(n--)
    {
        char op[2];
        int x;
        scanf("%s%d",op,&x);
        if(*op == 'I')
        {
            h[find(x)] = x;
        }
        else
        {
            if(h[find(x)]==null) puts("No");//puts自带换行输出
            else puts("Yes");
        }
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值