存储结构1.开放寻址法2.拉链法
哈希表
字符串哈希方式
-10e9~10e9;
映射到h(x) 0~1e5;
1、 xmod 1e5 属于范围
2、可以会产生冲突 因为数据范围过大的原因
与离散化的区别
离散化需要保序例如单调递增//可以看成是极其特殊的一种哈希方式
1、拉链法
操作
1可以添加一个数h(x)
2查找一个数:
看一下h(x)在哪个槽上
遍历一个这个槽对应的链表
3如果要实现删除一个数
不会真的删除开一个bool数组如果删除标记一下就可以
自信点就是邻接表
0 1 2 3 4 10e5
| |
[11] []
| |
[13] []
|
[]
顾名思义拉链子 链子长度看成一样的1就行
开一个槽h[N];
拉一个链表
idx表示当前用到哪一个位置;
e[N]ne[N]表示当前的数值和下一个位置在什么地方;
k是哈希值
拉一个链表
memset(h,-1,sizeofh);把所有的槽清空一下空指针一般用-1表示
intsert
1 k 1e5
| o e[idx]=x ne[idx]=h[x] h[x]=idx++; idx后++;
[]
|
[]
#include <cstring>
#include <iostream>
using namespace std;
const int N = 100003;
int h[N], e[N], ne[N], idx;
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 n;
scanf("%d", &n);
memset(h, -1, sizeof h);
while (n -- )
{
char op[2];
int x;
scanf("%s%d", op, &x);
if (*op == 'I') insert(x);
else
{
if (find(x)) puts("Yes");
else puts("No");
}
}
return 0;
}
开放寻址法
一般开一个一维数组不用拉链子
一般是开到题目描述数组的2——3倍十万就开成二十万
添加
[][][][1][1][1][1][][][]
先找到k然后从第k个坑位开始
直到找到一个空的坑位置插进去
查找
先找到k然后从第k个坑位开始
如果当前坑位有人并且是x我们就找到了
如果当前坑有人不是坑我们就看下一个坑
如果当前坑没人就是不存在
删除[一般用不到]
一般找到x在数组当中标记一下
先找到大于二十万的最小质数
for(int i=200000;;i++)
{
bool fg=1;
for(int j=2;j*j<i;j++)
{
fg=0;
break;
}
if(fg)
{
cout<<i<<endl;
break;
}
}
运行得出200003
find函数如果x在哈希表中的话
则返回x的位置如果不在的话就返回x应该存放的位置
#include <cstring>
#include <iostream>
using namespace std;
const int N = 200003, null = 0x3f3f3f3f;
int h[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;
}
int main()
{
memset(h, 0x3f, sizeof h);
int n;
scanf("%d", &n);
while (n -- )
{
char op[2];
int x;
scanf("%s%d", op, &x);
if (*op == 'I') h[find(x)] = x;
else
{
if (h[find(x)] == null) puts("No");
else puts("Yes");
}
}
return 0;
}
作者:一万小时定律
链接:https://www.acwing.com/solution/content/122014/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。