算法:模拟散列表(哈希拉链法,开放选址法)

拉链法:

用数组h[N]来表示拉链法上对应的链,如果遇到冲突则在对应冲突的位置开一个链,创建链的方式和之前单链表的方式相同。如果要插入一个值:

  1. 计算当前值在哈希之后的映射位置int k = (x % N + N) % N;之所以要取两次模,是为了处理负数的模
  2. 将x存储在e[idx]中
  3. 该链表的下一个位置就是当前冲突位置的链表的头,故ne[idx] = h[k];
  4. 当前冲突位置链表的头变为了当前的idxh[k] = idx++;

开放选址法

只需要一个一维数组用来存储。
在插入时遇到冲突,按数组顺序向后查找,直到找到空位置将其插入。
在查找时,从哈希映射的位置开始查找,如果找到这个值,则返回其下标,如果直到当前位置为空时,还没有找到,则说明该值不存在。
取余的数应该是一个质数,并且应该大于题目要求的两倍。

问题描述

维护一个集合,支持如下几种操作:

“I x”,插入一个数x;
“Q x”,询问数x是否在集合中出现过;
现在要进行N次操作,对于每个询问操作输出对应的结果。

输入格式

第一行包含整数N,表示操作数量。

接下来N行,每行包含一个操作指令,操作指令为”I x”,”Q x”中的一种。

输出格式

对于每个询问指令“Q x”,输出一个询问结果,如果x在集合中出现过,则输出“Yes”,否则输出“No”。

每个结果占一行。

数据范围

1≤N≤105
−109≤x≤109

输入样例:

5
I 1
I 2
I 3
Q 2
Q 5

输出样例:

Yes
No

代码1

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

const int N = 100003;
int h[N], e[N], ne[N], idx = 0;

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 m;
    memset(h, -1, sizeof h);
    cin >> m;
    while(m --){
        string s;
        int x;
        cin >> s >> x;
        if(s == "I"){
            insert(x);
        }else{
            if(find(x)){
                cout << "Yes" << endl;
            }else{
                cout << "No" << endl;
            }
        }
    }
    return 0;
}

代码2

#include<iostream>
#include<cstring>
using namespace std;

const int N = 200003;
int null = 0x3f3f3f3f;
int h[N];

int find(int x){
    int k = (x % N + N) % N;
    for(int i = k; ; ++i){
        if(h[i] == null){
            return i;
        }
        if(h[i] == x){
            return i;
        }
    }
    
    return k;
}

int main(){
    int m;
    memset(h, null, sizeof h);
    cin >> m;
    while(m --){
        string s;
        int x;
        cin >> s >> x;
        if(s == "I"){
            int k = find(x);
            h[k] = x;
        }else{
            if(h[find(x)] != null){
                cout << "Yes" << endl;
            }else{
                cout << "No" << endl;
            }
        }
    }
    return 0;
}

原题链接

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

evil心安

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值