哈希表

拉链法

哈希函数: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);
}

字符哈希表

posted @ 2024-07-27 21:36  某朝  阅读(20)  评论(0)    收藏  举报