Acwing Hash表
哈希表的作用:把一个比较大的空间,通过一个函数映射到一个比较小的空间
一般做哈希运算时,取一个质数作为模,会使得冲突的概率降低。
哈希表的冲突解决方法:
- 拉链法
- 开放寻址法
下面详细介绍这两种方法的原理及其实现:
1.拉链法
创建一个数组h[],插入一个值时通过哈希函数映射到数组对应位置,每个位置维护一个链表,映射到相同位置加入当前链表中。
数组h[i]类似于链表的头指针,存储的是其下链表的第一个结点x的数组下标**,而不是结点的值x,取值范围0~N,所以可以让数组h的默认值为-1,以此判断该位置下是否为空
- 插入操作:采用头插法,根据哈希函数计算哈希值,每次冲突的值,插入到链表的第一个位置;
- 查询操作:根据哈希值找到对应头指针即对应链表,再对链表遍历判断;
- 删除操作:删除操作并不是真正的删除该元素,而是设置一个标记值,来表示该位置的值已被删除(用得少)。
板子:
const int N = 100003; // 大于10^5的最小质数,作为哈希表的大小int h[N], e[N], ne[N], idx = 0;
// h[] 用于存储每个哈希值对应的链表头结点
// e[] 用于存储插入的值
// ne[] 用于存储每个元素的下一个节点的索引
// idx 是当前插入元素的索引// 插入操作,使用拉链法实现
void insert(int x){int k = (x % N + N) % N; // 计算哈希值,处理负数时确保结果为正数e[idx] = x; // 将x存入数组e,idx是当前存储的索引ne[idx] = h[k]; // 将当前元素的下一个节点设置为链表的第一个节点h[k] = idx++; // 将哈希表h[k]指向当前元素,并更新idx
}// 查找操作,查找元素x是否存在
bool find(int x){int k = (x % N + N) % N; // 计算哈希值for(int i = h[k]; i != -1; i = ne[i]){ // 遍历哈希表k对应的链表if(e[i] == x) return true; // 如果找到,返回true}return false; // 没找到,返回false
}
哈希表常用取余法,代码实现找一个大于等于N且最小的质数:
int get_Prime(int N){for(int i = N;;i++){bool flag = true;for(int j = 2; j * j <= i;j ++){if(i % j== 0){flag = false;break;}}if(flag){return i;break;}}
}
2.开放寻址法:
开放寻址法:当冲突发生时,使用某种探测算法(得出一个偏移量)在散列表中寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到。探测法有线性探测法、平方探测法、双散列法、伪随机序列。这里直接使用线性探测法,即冲突则自增1。
数组h[]存储的时具体的节点值x,而x的取值范围是 − 1 0 9 − − 1 0 9 -10^9 --10^9 −109−−109.故应该让数组x的默认值不在x的取值范围内(定义null = 0x3f3f3f3f),这样才好判断h[k[位置上是否为空(注意和拉链法区分)
- 查找和查询操作合为一个find()函数:首先根据哈希函数计算的哈希值查找当前元素是否在初始位置。若该位置为空,则在这个位置插入该元素;若不为空且与该元素不等,则向后继续查找,直到找到该元素或有空位置则插入该元素。最后返回该位置。
板子:
const int N = 200003, null = 0x3f3f3f3f; // N为哈希表的大小,null为标志无效值的常量
int h[N]; // 哈希表,存储元素// 开放寻址法查找函数
// 如果x在哈希表中,返回x的下标;
// 如果x不在哈希表中,返回x应该插入的位置
int find(int x) {int k = (x % N + N) % N; // 计算哈希值,处理负数使其为正while(h[k] != null && h[k] != x) { // 当位置不为空且不等于x时,进行线性探测k++; // 如果发生冲突,继续探测下一个位置if(k == N) k = 0; // 如果到达末尾,回到哈希表开头}return k; // 返回找到的插入位置或x所在的位置
}
好的,下面给出一道题目,我们采用两种方法解答:
Acwing 840. 模拟散列表

输入样例:
5
I 1
I 2
I 3
Q 2
Q 5
输出样例:
Yes
No
具体实现(2种):
//拉链法
#include <iostream>
#include <cstring>using namespace std;const int N = 100003; // 大于10^5的最小质数,作为哈希表的大小int h[N], e[N], ne[N], idx = 0;
// h[] 用于存储每个哈希值对应的链表头结点
// e[] 用于存储插入的值
// ne[] 用于存储每个元素的下一个节点的索引
// idx 是当前插入元素的索引// 插入操作,使用拉链法实现
void insert(int x){int k = (x % N + N) % N; // 计算哈希值,处理负数时确保结果为正数e[idx] = x; // 将x存入数组e,idx是当前存储的索引ne[idx] = h[k]; // 将当前元素的下一个节点设置为链表的第一个节点h[k] = idx++; // 将哈希表h[k]指向当前元素,并更新idx
}// 查找操作,查找元素x是否存在
bool find(int x){int k = (x % N + N) % N; // 计算哈希值for(int i = h[k]; i != -1; i = ne[i]){ // 遍历哈希表k对应的链表if(e[i] == x) return true; // 如果找到,返回true}return false; // 没找到,返回false
}int main(){memset(h, -1, sizeof h); // 初始化哈希表h,令所有值为-1,表示链表为空int n; // 操作数cin >> n;while(n--){ // 处理n个操作char op[2]; // 操作符int x; // 操作的数值cin >> op >> x;if(op[0] == 'I') insert(x); // 插入操作else { // 查找操作if(find(x)) puts("Yes"); else puts("No"); }}return 0;
}
//开放寻址法
#include <iostream>
#include <cstring>using namespace std;const int N = 200003, null = 0x3f3f3f3f; // N为哈希表的大小,null为标志无效值的常量
int h[N]; // 哈希表,存储元素// 开放寻址法查找函数
// 如果x在哈希表中,返回x的下标;
// 如果x不在哈希表中,返回x应该插入的位置
int find(int x) {int k = (x % N + N) % N; // 计算哈希值,处理负数使其为正while(h[k] != null && h[k] != x) { // 当位置不为空且不等于x时,进行线性探测k++; // 如果发生冲突,继续探测下一个位置if(k == N) k = 0; // 如果到达末尾,回到哈希表开头}return k; // 返回找到的插入位置或x所在的位置
}int main() {//memset按字节赋值,int4个字节,每个字节赋值0x3f,则h默认值就为0x3f3f3f3f 即nullmemset(h, 0x3f, sizeof h); // 初始化哈希表,所有位置都标记为nullint n; // 操作次数cin >> n;while(n--) {char op[2]; // 操作类型int x; // 操作的数值cin >> op >> x;int k = find(x); // 通过find函数得到x的位置if(op[0] == 'I') h[k] = x; // 插入操作,将x放入找到的位置else {if(h[k] != null) puts("Yes"); // 如果h[k]不是null,说明x在哈希表中else puts("No"); // 否则x不在哈希表中}}return 0;
}
以上两种方法各有利弊,开放寻址法通过线性探测有效解决哈希冲突,适合负载率较低的哈希表。在实际操作中,开放寻址法避免了链表(拉链法)的额外存储开销,但在负载率高时可能会导致较多的探测,影响性能。个人倾向于开放寻址法,只需要开一个数组~
相关文章:
Acwing Hash表
哈希表的作用:把一个比较大的空间,通过一个函数映射到一个比较小的空间 一般做哈希运算时,取一个质数作为模,会使得冲突的概率降低。 哈希表的冲突解决方法: 拉链法开放寻址法 下面详细介绍这两种方法的原理及其实现…...
大健康裂变分销小程序开发
大健康裂变分销小程序的开发是一个涉及技术、市场策略、用户体验和合规性等多个方面的综合项目。这类小程序旨在通过分销机制促进大健康产品的销售和品牌推广,同时利用社交网络的裂变效应扩大市场影响力。以下是大健康裂变分销小程序开发的主要步骤和考虑因素&#…...
js取出一个对象中指定的字段(封装公共方法)
需求:在一个对象里面挑选出所需要的一个或多个字段 例子:在{ a: 1, b: 2, c: 3, d: 4 }里面挑选出b和d字段 封装公共方法 const pick (obj, keys) > {return Object.keys(obj).filter(key > keys.includes(key)).reduce((result, key) > {if …...
【黑马点评】已解决java.lang.NullPointerException异常
Redis学习Day3——黑马点评项目工程开发-CSDN博客 问题发现及描述 在黑马点评项目中,进行到使用Redis提供的Stream消息队列优化异步秒杀问题时,我在进行jmeter测试时遇到了重大的错误 发现无论怎么测试,一定会进入到catch中,又由…...
计算机专业的就业方向
计算机专业的就业方向 亲爱的新生们,欢迎你们踏上计算机科学的旅程!作为一名计算机专业的学生,你们即将进入一个充满无限可能的领域。今天,我将为大家介绍计算机专业的一些主要就业方向,帮助你们了解未来的职业选择。…...
VSCode C++ Tasks.json中的变量
前言 上文介绍了在VSCode中创建C项目和编译多文件的情况。本文将介绍Tasks.json中一些变量的含义; 内容 tasks.json文件 下文参考VSCode文档:Visual Studio Code 变量参考 预定义标量 ${userHome} - 用户主文件夹的路径${workspaceFolder} - 在 VS Co…...
第一次安装Pytorch
1、新版本的Anaconda内置的python版本是3.12, 目前 Windows 上的 PyTorch 仅支持 Python 3.8-3.11;不支持 Python 2.x。 1、创建运行环境 在不创建虚拟环境的情况下,不建议使用最新的Python和Anaconda。 在几次失败后,我使用的是Anaconda3-2…...
Python数据分析-Steam 收入排名前 1500 的游戏
一、研究背景 随着全球数字化进程的加速,电子游戏产业已成为全球娱乐产业的重要组成部分,吸引了越来越多的资本与消费者关注。特别是基于互联网的游戏平台,如Steam,已成为全球范围内发行和销售游戏的重要渠道。Steam平台不仅为玩…...
Android14请求动态申请存储权限
Android14请求动态申请存储权限 Android14和Android15存储权限有增加多了选择部分,还是全部。一个小小的存储权限真的被它玩出了花来。本来Android13就将存储权限进行了3个细分,是图片,音频还是视频文件。 步骤一:AndroidManife…...
Doris:数据库建表最佳实践
目录 一、表模型推荐归约 二、字段推荐归约 三、建表推荐归约 四、建表强制归约 五、最佳实践 Doris 数据表模型上目前分为三类:DUPLICATE KEY, UNIQUE KEY, AGGREGATE KEY。因为数据模型在建表时就已经确定,且无法修改。所以,选择一个合…...
Parallels Desktop 20(Mac虚拟机) v20.0.0 for Mac 最新破解版(支持M系列)
Parallels Desktop 20 for Mac 正式发布,完全支持 macOS Sequoia 和 Windows 11 24H2,并且在企业版中引入了全新的管理门户。 据介绍,新版本针对 Windows、macOS 和 Linux 虚拟机进行了大量更新,最大的亮点是全新推出的 Parallels…...
【已解决】华为AR100-S路由器 恢复出厂后,找不到5G wifi的设置
前两帖讨论了华为AR100-S路由器: 一是用电脑浏览器访问web管理界面报错的解决,详情点这里! https://blog.csdn.net/weixin_62598385/article/details/142215136 再就是如何回复出厂,也即如何复位, 详情点这里ÿ…...
【MongoDB】--MongoDB批量操作
目录 一、批量更新 一、批量更新 /*** 批量更新的操作* return*/public int batchUpdate(){List<StudentDo> list new ArrayList<>(); //要修改的一批数据List<Pair<Query, Update>> updateList new ArrayList<>(list.size());BulkOperations …...
数据库常规操作
常用的 SQL 语法和操作: 数据定义语言(DDL) 1.创建数据库CREATE DATABASE database_name;2.删除数据库DROP DATABASE database_name;3.创建表CREATE TABLE table_name (column1 datatype constraints,column2 datatype constraints,...);4.删…...
基于STM32设计的水渠闸门远程控制系统(华为云IOT)(226)
文章目录 一、前言1.1 项目介绍【1】开发背景【2】项目实现的功能【3】项目硬件模块组成【4】ESP8266工作模式配置1.2 设计思路【1】整体设计思路【2】整体构架【3】上位机开发思路1.3 项目开发背景【1】选题的意义【2】可行性分析【3】参考文献【4】摘要1.4 开发工具的选择【1…...
鸿蒙开发(NEXT/API 12)【响应校验】远场通信服务
本协议栈框架支持校验响应功能,应用添加了响应校验器后,可在ResponseValidationCallback中判断响应是否符合预期,不符合那么框架会抛异常。 开发步骤 导包。 import { rcp } from kit.RemoteCommunicationKit;添加响应校验器并且发起请求。 …...
2024最新!!!iOS高级面试题,全!(二)
iOS应用是如何启动以及如何优化 pre-main阶段 加载动态链接器dyld到App进程 加载动态库(包括所依赖的所有动态库) Rebase 修正内部的指针指向 Bind 修正外部指针指向 初始化Objective C Runtime 包括oc的类、分类的注册,selector唯一性检查等…...
【C#生态园】构建你的C#操作系统:框架选择与实践
探秘C#操作系统开发框架:从框架选择到实际应用 前言 在当今信息技术高度发达的时代,操作系统开发框架为软件工程师提供了全新的可能性。本文将介绍一系列用于C#的操作系统开发框架,探讨它们的核心功能、使用场景、安装与配置方法以及API概览…...
ADB 安装教程:如何在 Windows、macOS 和 Linux 上安装 Android Debug Bridge
目录 一、ADB 介绍 二、Windows 系统安装 ADB 1. 下载 ADB 2. 解压文件 3. 验证 ADB 安装 4. 配置环境变量 5. 验证全局 ADB 使用 三、macOS 系统安装 ADB 1. 下载 ADB 2. 解压文件 3. 配置环境变量 4. 验证 ADB 安装 四、Linux 系统安装 ADB 1. 使用包管理器安装…...
java(2)方法的使用
目录 1.前言 2.正文 2.1方法的定义 2.2方法的调用过程 2.3方法的实参与形参 2.3.1形参 2.3.2实参 2.3.3参数传递 2.4方法的重载 3.小结 1.前言 哈喽大家好啊,今天博主继续带领大家学习java的基本语法,java的基础语法部分打算用六到七篇博文完…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...
回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...
人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...
