- 模拟散列表
维护一个集合,支持如下几种操作:
I x,插入一个数 x;
Q x,询问数 x 是否在集合中出现过;
现在要进行 N 次操作,对于每个询问操作输出对应的结果。
输入格式
第一行包含整数 N,表示操作数量。
接下来 N 行,每行包含一个操作指令,操作指令为 I x,Q x 中的一种。
输出格式
对于每个询问指令 Q x,输出一个询问结果,如果 x 在集合中出现过,则输出 Yes,否则输出 No。
每个结果占一行。
数据范围
1≤N≤10的5
−10的9≤x≤10的9
输入样例:
5
I 1
I 2
I 3
Q 2
Q 5
输出样例:
Yes
No
emmmm
1.分析样例(拉链法)
x的范围为−10的9≤x≤10的9范围很大且其数据个数相对的较少为10的5,因此我们可以想办法将数据映射进10的5次方,这时我们根据题目选择N=100003;作为除数将其处理映射较好,因为它是个素数能降低数据映射后的冲突,使其数据分散能相对均匀。
h[N] 将数据映射后的数组,也就是拉链数组。
n[N] 保留原数特征的数组。
ne[N] 存储前驱其相应位置。
idx; ne数组的位置;
重要的的函数
- insert
N=100003;
void insert(int num)
{
int x=(num%N+N)%N;//将其映射进相应区间,c++中负数余一个数为负数。
n[x]=num;//原数据的特征。
ne[x]=h[x];//该数据拉链的地址。
h[x]=idx++;//拉链存储的最后插入的数据的地址。
}
2.find
bool find(int num)
{
int x=(num%N+N)%N;//处理数据好到相应的链中找数据。
while(int k=h[x];k!=-1;k=ne[k])
{
if(n[k]==num)
return true;//找到喽
}
return false;//没找到**。
}
#include<iostream>
#include<cstring>
using namespace std;
const int N = 1e5+3;
int h[N],n[N],ne[N],idx;
void insert(int num)
{
int x = (num % N + N) % N;//将x映射成另一个值。
n[idx] = num;
ne[idx] = h[x];
h[x] = idx++;
}
bool find(int num)
{
int x = (num % N + N) % N;
for(int k = h[x];k != -1;k = ne[k])
{
if(n[k] == num)
{
return true;
}
}
return false;
}
int main()
{
int num,sum;
char op;
cin>>num;
memset(h,-1,sizeof(h));
for(int k=1;k<=num;k++)
{
cin>>op>>sum;
if(op=='I')
{
insert(sum);
}
else if(op=='Q')
{
if(find(sum))
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
}
return 0;
}
开放寻址法(蹲坑法)
1.一个数经过处理后查看其所对应的坑位有无数占用有则向后查找,返回其应该占用的坑位位置。
2.主要函数int find()
这里数组大小应该开到数据个数的2-3倍。
int x=(num%N+N)+N;
while(h[x]!=null&&h[x]!=num)//当前位置没有为空且不等于num(也就是没有找到);
{
x++;
if(x==N)//防止越界
x=0;
}
return x;//返回应该他应该存储的地址或其所在的地址。
#include<iostream>
#include<cstring>
using namespace std;
const int N=2e5+3,null=0x3f3f3f3f;
int h[N];
int find(int num)
{
int x=(num%N+N)%N;
while(h[x]!=null&&h[x]!=num)
{
x++;
if(x==N)
x==0;
}
return x;
}
int main()
{
int num,sum;
char op;
cin>>num;
memset(h,0x3f,sizeof(h));
for(int k=1;k<=num;k++)
{
cin>>op>>sum;
if(op=='I')
{
h[find(sum)]=sum;
}
else
{
if(h[find(sum)]!=null)
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
}
return 0;
}