本系列所有题目均为Acwing课的内容,发表博客既是为了学习总结,加深自己的印象,同时也是为了以后回过头来看时,不会感叹虚度光阴罢了,因此如果出现错误,欢迎大家能够指出错误,我会认真改正的。同时也希望文章能够让你有所收获,与君共勉!

今晚太晚了,就少些一点算了。

模拟散列表

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

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

输入格式
第一行包含整数 N,表示操作数量。

接下来 N 行,每行包含一个操作指令,操作指令为 I xQ 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

算法原理

简单的讲一下哈希表是用来干什么的吧。哈希表主要是用来记录一个数它出现的次数,能够以较快的时间在集合中找到它,那么为什么会这样呢,主要是因为哈希表建立了一种映射关系将值给映射到某一段较小的区间内,每一个值都对应的一个键,这个键就能帮助我们在这个区间里较快的找对存储的值,但是有一个问题就是这样的映射关系很容易重复,即容易产生哈希冲突,而解决哈希冲突的办法有很多,这里主要介绍开放寻址和拉链法。
先来看开放寻址法怎么实现。主要思路就是给定一个数x,通过加一个特别大的数再取余数转换成对应的键(x%N+N)%N,在哈希表中找没人(数字)占的地方插入就行,如果这个地方被人插入过,那么就需要寻找没有被插入过的地方,具体代码实现如下。

int find(int x){
	int t = (x%N+N)%N;
	while(h[t]!=null  && h[t] != x){
		t ++ ;
		if(t == N) t = 0;
	}
	return t;
}

拉链法明天再讲吧。

代码实现

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 200003,null = 0x3f3f3f3f;
int h[N];   // 厕所哦
int n;

int find(int x){
    int t = (x%N+N)%N;
    while(h[t]!=null && h[t]!=x){
        t++;
        if(t == N) t = 0;
    }
    return t;   // 如果存在返回x的厕所编号,不存在就返回要上厕所的编号
}

int main()
{
    cin >> n;
    memset(h,0x3f,sizeof h);
    while(n--){
        char op[2];
        int x;
        scanf("%s%d",op,&x);
        int t = find(x);
        if(*op == 'I'){
            h[t] = x;
        }
        else{
            if(h[t] != null){
                puts("Yes");
            }
            else{
                puts("No");
            }
        }
    }
    return 0;
}

原文地址:http://www.cnblogs.com/WangChe/p/16901920.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性