5.21
哈希表
Hash表又称为散列表,一般由Hash函数(散列函数)与链表结构共同实现,与离散化思想类似。
一般要求:防止冲突,便于查询
模拟hash表:
-
拉链法:两个核心操作insert(),find();
-
int h[N], e[N], ne[N], idx; //邻接表进行存储;
-
-
void insert(int x) { // c++中如果是负数 那他取模也是负的 所以 加N 再 %N 就一定是一个正数 int k = (x % N + N) % N; //hash防冲突取值 e[idx] = x; //赋值 ne[idx] = h[k]; //h[k]是一个拉链的结点,例如2下面的拉链; h[k] = idx++; //通过拉链进行延申 }
-
bool find(int x) { //用上面同样的 Hash函数 讲x映射到 从 0-1e5 之间的数 int k = (x % N + N) % N; for (int i = h[k]; i != -1; i = ne[i]) { //经典的邻链表的遍历操作; if (e[i] == x) { return true; //能找到 } } return false; }
-
例题链接:https://www.acwing.com/problem/content/842/
-
#include "cstring" #include "iostream" using namespace std; const int N = 100003; int h[N], e[N], ne[N], idx; void insert(int x) { int t = (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() { // for (int i = 100000; i; i++) { // bool flag = true; // for (int j = 2; j * j < i; j++) { // if (i % j == 0) { // flag = false; // break; // } // } // if (flag) { // cout << i; // break; // } // } //这里是找到N的操作,一般是取质数为hash计算的最好办法 memset(h, -1, sizeof h); //将槽先清空 空指针一般用 -1 来表示 int m; cin >> m; while (m--) { char op; int x; cin >> op >> x; if (op == 'I') { insert(x); } else { if (find(x)) cout << "Yes" << endl; else cout << "No" << endl; } } return 0; }0; }< "No" << endl; } } return 0; }
-
开放寻址法(推荐):
-
其实就是开辟两到三倍的一维数组空间大小来存放原来的数值;
-
主要方法:find(int x)找到x;两种结果
-
如果能找到,就返回x的下标,同时也对应着query操作
-
如果不能找到,那么返回x需要被插入的位置,对应着insert的操作;
-
-
#include "cstring" #include "iostream" using namespace std; const int N = 200003, null = 0x3f3f3f3f; int h[N]; int find(int x) { //找一个数是否存在,结果两种:一是存在的话,就返回它的位置,如果不存在,那么就需要返回它被插入的位置; int k = (x % N + N) % N; //散列原数,同时也找到x的位置 while (h[k] != null && h[k] != x) { //如果k位置的元素是空要么k位置的元素就是x的位置,那么就不需要判断,直接返回k就是要找的位置 k++; //如果当前位置被人家占了,就往后挪,直到N数组总长。总长都不够就从头开始 if (k == N) k = 0; } return k; } int main() { int m; cin >> m; memset(h, 0x3f, sizeof h); //对所有元素初始化为null配合h[k]!=null的查找 while (m--) { char op; int x; cin >> op >> x; int k = find(x); if (op == 'I') h[k] = x; //直接将k的位置给x元素就行 else { if (h[k] != null) //说明存在元素; cout << "Yes" << endl; else cout << "No" << endl; } } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)