AcWing 840. 模拟散列表

题目传送门

一、什么是散列表

又称哈希表,将一个比较大的值域映射到一个小的范围,比如0109,映射到0105范围内。原因是原来的值域是比较稀疏的,稠密的。

类似于离散化,离散化保序,而哈希表不保序。离散化是一种极其特殊的Hash方式。

一般的操作有:

  • 插入
  • 查找
  • 删除(一般不用)

二、拉链法

#include <bits/stdc++.h>

using namespace std;
const int N = 100003; //这个数字是根据FindGreaterPrime.cpp获取到的

//槽
int h[N];

//拉链法
int e[N], ne[N], idx;

//单链表插入
void insert(int x) {
    //如果x是负数,那么x%N就是一个负数,我们不想要一个负数,就加上一个N,
    //然后再模N就行了。
    int k = (x % N + N) % N;
    //头插法
    //1、添加一个新数据
    //2、原来k的头接到新增加数据idx的后面
    //3、把idx设置为k的头
    //4、idx++方便下一次插入
    e[idx] = x, ne[idx] = h[k], h[k] = idx++;
}

//查询操作
bool find(int x) {
    //同样的Hash函数
    int k = (x % N + N) % N;
    //查找链表,看看有没有x
    for (int i = h[k]; i != -1; i = ne[i])
        if (e[i] == x) return true;
    return false;
}

int main() {
    //优化输入
    ios::sync_with_stdio(false);
    int n;
    cin >> n;

    //批量设置h数组内容为-1,清空槽,这是链表终点的初始值
    memset(h, -1, sizeof h);

    while (n--) {
        string op;
        int x;
        cin >> op >> x;
        //插入x
        if (op == "I") insert(x);
        else {
            //检查是不是存在
            if (find(x)) puts("Yes");
            else puts("No");
        }
    }
    return 0;
}

三、开放寻址法

#include <bits/stdc++.h>

using namespace std;

//如果题目说是100000,那就需要找一个两倍大一点的质数
//这个数字是根据FindGreaterPrime.cpp获取到的
const int N = 200003;

//正无穷
const int INF = 0x3f3f3f3f;
//因为题目的数据范围是1e9,而0x3f3f3f3f大于1e9,所以可以用来做特殊值判断

//开放寻址法
int h[N];

//核心操作
//找坑位:有两种方式会停止下来,一是找到了这个值,二是找到了坑位,用时再注意分辩
//如果存在,返回x存储的位置
//如果不存在,返回x应该存储的位置
//如果返回的位置上真实的值==x就是找到了,!=x就是找不到
int find(int x) {
    int k = (x % N + N) % N;
    while (h[k] != INF && h[k] != x) {
        k++;
        if (k == N) k = 0;//如果找到了最后一个位置,那么就回到0
    }
    return k;
}

int main() {
    //输入优化
    ios::sync_with_stdio(false);

    int n;
    cin >> n;
    //全部初始化为正无穷,判断是不是使用过此位置
    memset(h, 0x3f, sizeof h);

    while (n--) {
        string op;
        int x;
        cin >> op >> x;
        int k = find(x);
        if (op == "I")h[k] = x;
        else {
            if (h[k] != INF) puts("Yes");
            else puts("No");
        }
    }
    return 0;
}

四、找出大于n的第一个质数

#include <bits/stdc++.h>

using namespace std;

//判断一个数是不是质数
bool isPrime(int n) {
    if (n < 2) return false;
    for (int i = 2; i <= n / i; i++)
        if (n % i == 0) return false;
    return true;
}

int main() {
    for (int i = 100000;; i++) {
        if (isPrime(i)) {
            cout << i << endl;
            break;
        }
    }
    return 0;
}
posted @   糖豆爸爸  阅读(640)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
历史上的今天:
2014-09-16 win7或win2008系统中,出现【已停止工作,联机检查解决方案并关闭该程序,关闭程序】解决方法!
2014-09-16 Mysql的碎片查看与处理
2013-09-16 linux下vi命令大全
2013-09-16 农安实施的思路
Live2D
点击右上角即可分享
微信分享提示