- 将一个大的空间的数据或者无法处理的空间的数据通过映射函数映射到一个小的容易处理的空间,但是在映射之后可能会出现不同的元素映射之后值相同的情况,这时就需要处理冲突,有两种方法分别是拉链法和开放寻址法
维护一个集合,支持如下几种操作:
- “I x”,插入一个数x;
- “Q x”,询问数x是否在集合中出现过;
现在要进行N次操作,对于每个询问操作输出对应的结果。
输入格式
第一行包含整数N,表示操作数量。
接下来N行,每行包含一个操作指令,操作指令为”I x”,”Q x”中的一种。
输出格式
对于每个询问指令“Q x”,输出一个询问结果,如果x在集合中出现过,则输出“Yes”,否则输出“No”。
每个结果占一行。
数据范围
1≤N≤1051≤N≤105
−109≤x≤109−109≤x≤109
输入样例:
5
I 1
I 2
I 3
Q 2
Q 5
输出样例:
Yes
No
####################################################
1 #include <bits/stdc++.h> 2 using namespace std; 3 //拉链法处理哈希冲突,冲突指的是比如: 5 % 3 = 2,8 % 3 = 2,那么5和8就是冲突元素,所以把5和8挂在一个单链表上 4 const int N = 1e5+3;//这个数在哈希函数中最好是质数、 5 vector<int> ha(N, -1);//ha数组存的是头节点的next 6 int e[N], ne[N], idx; 7 8 void insert(int x){ 9 int k = (x%N + N) % N;//哈希函数把一个大的数据范围转变成0到n一个范围,因为有负数所以需要+N再膜N,为了变成正数 10 e[idx] = x; 11 ne[idx] = ha[k]; 12 ha[k] = idx ++; 13 } 14 bool find(int x){ 15 int k = (x%N + N)%N; 16 int p = ha[k]; 17 while(p != -1){ 18 if(e[p] == x)return true; 19 else p = ne[p]; 20 } 21 return false; 22 } 23 24 int main(){ 25 int n; 26 cin >> n; 27 while(n --){ 28 string op; 29 int x; 30 cin >> op >> x; 31 if(op == "I")insert(x); 32 else{ 33 if(find(x))cout << "Yes" << endl; 34 else cout << "No" << endl; 35 } 36 } 37 return 0; 38 }
方法二:
1 //开放寻址法 2 #include <bits/stdc++.h> 3 using namespace std; 4 5 const int N = 2e5+3;//N 取数据范围的2~3倍,然后再取质数,这样冲突会少(结论) 6 const int null = 0x3f3f3f; 7 vector<int> ha(N,null); 8 9 //返回x映射后正确的存放位置 10 int find(int x){ 11 int t = (x%N+N)%N; 12 while(ha[t] != null && ha[t] != x){ 13 ++t; 14 if(t == N)t = 0; 15 } 16 return t; 17 } 18 19 int main(){ 20 int n; 21 cin >> n; 22 while(n --){ 23 string op; 24 int x; 25 cin >> op >> x; 26 if(op == "I"){ 27 ha[find(x)] = x; 28 }else{ 29 if(ha[find(x)] == null) cout << "No" <<endl; 30 else cout << "Yes" << endl; 31 } 32 } 33 }
end;