哈希表
拉链法
哈希函数:f(x) = ( x % N + N ) % N
k就是下标, h[k]=x
哈希表的头节点(head指针)是idx,就是第几个插入的序号
idx没什么用,用头插法插入元素,插入和寻找都是h[k]在起作用
idx会变,当插入第二个下标为k的元素时,idx就会变成新的。
#include<iostream>
using namespace std;
const int N = 100003;
//N 设为1个质数
int h[N];
int e[N], ne[N], idx;
//y总的找质数
void f() {
for (int i = 100000;; i++)
{
bool flag = true;
for (int j = 2; j * j <= i; j++)
if (i % j == 0)
{
flag = false;
break;
}
if (flag)
{
cout << i << endl;
break;
}
}
}
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; cin >> n;
//空指针设置为-1;
memset(h, -1, sizeof(h));
while (n--) {
char op[2];
int x;
cin >> op >> x;
if (*op == 'I') insert(x);
else
{
if (find(x))puts("Yes");
else puts("No");
}
}
}
将负数的余数变为正数
和数学中不同 c++中余数可以是负数 -10/3=-3···-1
需要把余数变为正数 int k = (x % N + N) % N;
开放寻址法
#include<iostream>
using namespace std;
const int N = 200003, null = 0x3f3f3f; //大于数据范围
int h[N];
// 如果 x 存在的话,则返回 x 的位置
// 如果 x 不存在的话,返回 x 的应该存储的位置 (第一个h[k]==null)
int find(int x)
{
int k = (x % N + N) % N;
//上厕所
while (h[k] != null && h[k] != x)
{
k++;
if (k == N)k = 0;//看到最后了,循环看第一个坑位
}
return k;
}
int main() {
int n;
cin >> n;
memset(h, null, sizeof(h));
while (n--) {
char op[2];
int x;
cin >> op >> x;
int k = find(x);
if (*op == 'I') h[k] = x;
else
{
if (h[k] != null)puts("Yes");
else puts("No");
}
}
}
字符哈希表
typedef unsigned long long ULL;
const int P = 131;
const int N = 100010;
ULL p[N], h[N];
int n;
char s[N];
void init() {
for (int i = 1; i <= n; i++)
{
p[0] = 1, h[0] = 0;
p[i] = p[i - 1] * P;
h[i] = h[i - 1] * P + s[i];
}
}
ULL get(int l, int r) {
return h[r] - h[l] * p[r - l + 1];
}
bool substr(int l1, int r1, int l2, int r2) {
return get(l1, r1) == get(l2, r2);
}