模拟散列表

  1. 模拟散列表

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

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数组的位置;

重要的的函数

  1. 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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值