当前位置: 首页 > news >正文

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 109109.故应该让数组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表

哈希表的作用&#xff1a;把一个比较大的空间&#xff0c;通过一个函数映射到一个比较小的空间 一般做哈希运算时&#xff0c;取一个质数作为模&#xff0c;会使得冲突的概率降低。 哈希表的冲突解决方法&#xff1a; 拉链法开放寻址法 下面详细介绍这两种方法的原理及其实现…...

大健康裂变分销小程序开发

大健康裂变分销小程序的开发是一个涉及技术、市场策略、用户体验和合规性等多个方面的综合项目。这类小程序旨在通过分销机制促进大健康产品的销售和品牌推广&#xff0c;同时利用社交网络的裂变效应扩大市场影响力。以下是大健康裂变分销小程序开发的主要步骤和考虑因素&#…...

js取出一个对象中指定的字段(封装公共方法)

需求&#xff1a;在一个对象里面挑选出所需要的一个或多个字段 例子&#xff1a;在{ 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博客 问题发现及描述 在黑马点评项目中&#xff0c;进行到使用Redis提供的Stream消息队列优化异步秒杀问题时&#xff0c;我在进行jmeter测试时遇到了重大的错误 发现无论怎么测试&#xff0c;一定会进入到catch中&#xff0c;又由…...

计算机专业的就业方向

计算机专业的就业方向 亲爱的新生们&#xff0c;欢迎你们踏上计算机科学的旅程&#xff01;作为一名计算机专业的学生&#xff0c;你们即将进入一个充满无限可能的领域。今天&#xff0c;我将为大家介绍计算机专业的一些主要就业方向&#xff0c;帮助你们了解未来的职业选择。…...

VSCode C++ Tasks.json中的变量

前言 上文介绍了在VSCode中创建C项目和编译多文件的情况。本文将介绍Tasks.json中一些变量的含义&#xff1b; 内容 tasks.json文件 下文参考VSCode文档&#xff1a;Visual Studio Code 变量参考 预定义标量 ${userHome} - 用户主文件夹的路径${workspaceFolder} - 在 VS Co…...

第一次安装Pytorch

1、新版本的Anaconda内置的python版本是3.12&#xff0c; 目前 Windows 上的 PyTorch 仅支持 Python 3.8-3.11;不支持 Python 2.x。 1、创建运行环境 在不创建虚拟环境的情况下&#xff0c;不建议使用最新的Python和Anaconda。 在几次失败后&#xff0c;我使用的是Anaconda3-2…...

Python数据分析-Steam 收入排名前 1500 的游戏

一、研究背景 随着全球数字化进程的加速&#xff0c;电子游戏产业已成为全球娱乐产业的重要组成部分&#xff0c;吸引了越来越多的资本与消费者关注。特别是基于互联网的游戏平台&#xff0c;如Steam&#xff0c;已成为全球范围内发行和销售游戏的重要渠道。Steam平台不仅为玩…...

Android14请求动态申请存储权限

Android14请求动态申请存储权限 Android14和Android15存储权限有增加多了选择部分&#xff0c;还是全部。一个小小的存储权限真的被它玩出了花来。本来Android13就将存储权限进行了3个细分&#xff0c;是图片&#xff0c;音频还是视频文件。 步骤一&#xff1a;AndroidManife…...

Doris:数据库建表最佳实践

目录 一、表模型推荐归约 二、字段推荐归约 三、建表推荐归约 四、建表强制归约 五、最佳实践 Doris 数据表模型上目前分为三类&#xff1a;DUPLICATE KEY, UNIQUE KEY, AGGREGATE KEY。因为数据模型在建表时就已经确定&#xff0c;且无法修改。所以&#xff0c;选择一个合…...

Parallels Desktop 20(Mac虚拟机) v20.0.0 for Mac 最新破解版(支持M系列)

Parallels Desktop 20 for Mac 正式发布&#xff0c;完全支持 macOS Sequoia 和 Windows 11 24H2&#xff0c;并且在企业版中引入了全新的管理门户。 据介绍&#xff0c;新版本针对 Windows、macOS 和 Linux 虚拟机进行了大量更新&#xff0c;最大的亮点是全新推出的 Parallels…...

【已解决】华为AR100-S路由器 恢复出厂后,找不到5G wifi的设置

前两帖讨论了华为AR100-S路由器&#xff1a; 一是用电脑浏览器访问web管理界面报错的解决&#xff0c;详情点这里&#xff01; https://blog.csdn.net/weixin_62598385/article/details/142215136 再就是如何回复出厂&#xff0c;也即如何复位&#xff0c; 详情点这里&#xff…...

【MongoDB】--MongoDB批量操作

目录 一、批量更新 一、批量更新 /*** 批量更新的操作* return*/public int batchUpdate(){List<StudentDo> list new ArrayList<>(); //要修改的一批数据List<Pair<Query, Update>> updateList new ArrayList<>(list.size());BulkOperations …...

数据库常规操作

常用的 SQL 语法和操作&#xff1a; 数据定义语言&#xff08;DDL&#xff09; 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)【响应校验】远场通信服务

本协议栈框架支持校验响应功能&#xff0c;应用添加了响应校验器后&#xff0c;可在ResponseValidationCallback中判断响应是否符合预期&#xff0c;不符合那么框架会抛异常。 开发步骤 导包。 import { rcp } from kit.RemoteCommunicationKit;添加响应校验器并且发起请求。 …...

2024最新!!!iOS高级面试题,全!(二)

iOS应用是如何启动以及如何优化 pre-main阶段 加载动态链接器dyld到App进程 加载动态库&#xff08;包括所依赖的所有动态库&#xff09; Rebase 修正内部的指针指向 Bind 修正外部指针指向 初始化Objective C Runtime 包括oc的类、分类的注册&#xff0c;selector唯一性检查等…...

【C#生态园】构建你的C#操作系统:框架选择与实践

探秘C#操作系统开发框架&#xff1a;从框架选择到实际应用 前言 在当今信息技术高度发达的时代&#xff0c;操作系统开发框架为软件工程师提供了全新的可能性。本文将介绍一系列用于C#的操作系统开发框架&#xff0c;探讨它们的核心功能、使用场景、安装与配置方法以及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.前言 哈喽大家好啊&#xff0c;今天博主继续带领大家学习java的基本语法&#xff0c;java的基础语法部分打算用六到七篇博文完…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

Linux 文件类型,目录与路径,文件与目录管理

文件类型 后面的字符表示文件类型标志 普通文件&#xff1a;-&#xff08;纯文本文件&#xff0c;二进制文件&#xff0c;数据格式文件&#xff09; 如文本文件、图片、程序文件等。 目录文件&#xff1a;d&#xff08;directory&#xff09; 用来存放其他文件或子目录。 设备…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

条件运算符

C中的三目运算符&#xff08;也称条件运算符&#xff0c;英文&#xff1a;ternary operator&#xff09;是一种简洁的条件选择语句&#xff0c;语法如下&#xff1a; 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true&#xff0c;则整个表达式的结果为“表达式1”…...

服务器硬防的应用场景都有哪些?

服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式&#xff0c;避免服务器受到各种恶意攻击和网络威胁&#xff0c;那么&#xff0c;服务器硬防通常都会应用在哪些场景当中呢&#xff1f; 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

Element Plus 表单(el-form)中关于正整数输入的校验规则

目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入&#xff08;联动&#xff09;2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...