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

哈希表和STL —— unorderde_set/unordered_map【复习笔记】

1. 哈希表的相关概念

1.1 哈希表的定义

哈希表,又称为散列表,是根据关键字直接进行访问的数据结构。

它通过一个哈希函数(Hash Function),建立了一种关键字和存储地址间的直接映射关系,将每个关键字映射到一个固定大小的数组中的一个位置,这个位置被称为哈希地址或索引。理想情况下,散列表的查找的时间复杂度为O(1),和表中元素数量无关

1.2 哈希冲突

1.2.1 哈希冲突的定义

哈希表可能把两个或两个以上的不同关键字映射到同一个地址,这种情况就叫哈希冲突,也加散列冲突,起冲突的不同关键字,称为同义词

1.2.2 处理哈希冲突的方法

1. 线性探测法

从冲突位置开始,依次线性向后探测,直到找到下一个没有存储数据的位置(如果走到哈希表尾,则返回哈希表头)

2. 链地址法

所有元素不直接存储到哈希表中,哈希表存储指针,每数据时指针为空,当有多个关键字映射到同一个位置,将这些数据串成链表,挂在该位置下面

1.3 哈希函数

1.3.1 哈希函数的定义

将关键字映射成对应地址的函数就是哈希函数,也叫散列函数,记为 Hash(key)= Addr 

1.3.2 常见的哈希函数

1. 直接定址法

直接取关键字的某个线性函数值作为散列地址,散列函数是 Hash(key)= a * key + b(a和b为常数)

2. 除留余数法

假设哈希表的大小为 M ,通过 key 除以 M 的余数作为映射位置的下标,散列函数是 Hash(key)= key % M

注意:

1. M 取不太接近 2 的整数次幂的一个质数。( 一般来讲,将关键字范围扩大 2 倍,取大于这个范围的质数即可)

2. key 有可能为负数,取模之后也会有负数。负数补正加上模数即可,但这样的活正数和负数的操作就不同一,为了方便,同一为 模加模

无论key是正数还是负数:( key % N + N )% N

3. 其他方法

数学分析法、平方取中法、折叠法、随机数法......这些方法相对局限

2. 哈希表的具体实现

案例:维护一个数据结构,初始为空,有以下操作:

           1 x:插入元素 x

           2 x:查询元素是否在数据结构中

输入描述:第一行一个整数 n ,表示操作次数 (假设插入操作次数小于10次)

                  之后 n 行,第 i 行两个整数 op、x,表示第 op 个操作和元素 x

2.1 除留取余法(哈希函数) + 线性探测法(处理哈希冲突)

#include<iostream>
#include<cstring>
using namespace std;
//根据题目的插入操作次数的范围,找到一个合适的模数创建哈希表
//范围扩大两倍,N 是质数
const int N = 23;
int h[N];//将哈希表的所有元素初始化为一个不会取到的值
//如果初始化为0或其他数,那可能无法辨别该数是初始数还是放入的数
//一般这个取不到的值为0x3f3f3f3f
const int INF = 0x3f3f3f3f;
void Init()
{memset(h, 0x3f, sizeof(h));
}//哈希函数返回映射位置
int h_f(int x)
{//模加模int id = (x % N + N) % N;//线性探测法处理哈希冲突while (h[id] != INF && h[id] != x){id++;if (id == N) id = 0;}return id;
}//插入元素
void insert(int x)
{int id = h_f(x);h[id] = x;
}//查找元素
bool find(int x)
{int id = h_f(x);return h[id] == x;
}
int main()
{Init();int n; cin >> n;while (n--){int op, x; cin >> op >> x;if (op == 1){insert(x);}else{if (find(x))cout << "yes" << endl;else cout << "no" << endl;}}return 0;
}

2.2 除留取余法(哈希函数) + 链地址法(处理哈希冲突)

该实现方法和(用数组实现树的遍历存储)中的链式前向星方法一样,本质是数组模拟链表

#include<iostream>
using namespace std;
#include<cstring>
//根据题目的插入操作次数的范围,找到一个合适的模数创建哈希表
//范围扩大两倍,N 是质数
const int N = 23;
int h[N];//数组模拟链表
int e[N], ne[N],id;//除留取余法
int f(int x)
{return (x % N + N) % N;
}//查找元素
bool find(int x)
{//得到 x 对应的哈希值int idx = f(x);//遍历链表for (int i = h[idx]; i; i = ne[i]){if (e[i] == x) return true;}return false;
}//插入元素
void insert(int x)
{//先判断该元素是否存在if (find(x)) return;int idx = f(x);//头插id++;e[id] = x;ne[id] = h[idx];h[idx] = id;
}int main()
{int n; cin >> n;while (n--){int op, x; cin >> op >> x;if (op == 1){insert(x);}else{if (find(x)) cout << "yes" << endl;else cout << "no" << endl;}}return 0;
}

3. unordered_set/unordered_multiset

unordered_set 和 set(红黑树和STL——set/map)的区别是,前者使用哈希表实现,而后者使用红黑树实现。导致的结果就是存储和查找的速率不一样,以及前者无序,后者有序,其他的使用方式完全一样。

而unordered_set 和 unordered_multiset 的区别:unordered_set 不能存相同的元素而unordered_multiset 可以存相同元素

#include<iostream>
#include<unordered_set>
using namespace std;int main()
{int arr[] = { 3,5,6,8,9,2,10,1 };unordered_set<int> mp;//begin/end:迭代器,可以用范围for遍历哈希表//和红黑树实现的 set 不同,遍历出来的结果是无序的for (auto& e : arr){//insert:插入,时间复杂度近似为O(1)mp.insert(e);}//find:查找一个元素,返回迭代器//count:查询一个元素出现的次数,一般用来判断该元素是否在哈希表中//时间复杂度都近似为O(1)if (mp.count(3)) cout << "yes" << endl;else cout << "no" << endl;//erase:删除元素,时间复杂度近似为O(1)mp.erase(3);if (mp.count(3)) cout << "yes" << endl;else cout << "no" << endl;//size:返回哈希表中元素个数,时间复杂度O(1)cout << mp.size() << endl;//empty:判断哈希表是否为空,时间复杂度O(1)if (mp.empty()) cout << "空" << endl;else cout << "非空" << endl;return 0;
}

4. unordered_map/unordered_multimap 

unordered_map 和 map(红黑树和STL——set和map)的区别是,前者使用哈希表实现,而后者使用红黑树实现。导致的结果就是存储和查找的速率不一样,以及前者无序,后者有序,其他的使用方式完全一样。

而unordered_map 和 unordered_multimap 的区别:unordered_map 不能存相同的元素而unordered_multimap 可以存相同元素

还有一点,无论是 map 还是 unordered_map 都可以存图,但 map 的查找速率较低,而 unordered_map 的查找速率较高

#include<iostream>
#include<unordered_map>
#include<vector>
using namespace std;void test()
{unordered_map<int, vector<int>> mp;mp[1].push_back(2);mp[2] = { 3, 4, 5 };mp[3].push_back(1);mp[3].push_back(2);for (auto& p : mp){cout << p.first << ":";for (auto& b : mp[p.first]) cout << b << " ";cout << endl;}
}int main()
{unordered_map<string, int> mp;//insert:插入元素,时间复杂度近似O(1)//用{}将元素括起来mp.insert({ "lili",1 });mp.insert({ "kiki",2 });mp.insert({ "vivi",3 });//c++17的结构化绑定for (auto& [k,v] : mp){cout << k << "编号:" << v << endl;}//operator[]:重载[],让unordered_map可以像数组一样使用//但operator[]可能会向 map 插入意料外的元素//插入时,第一个关键字为[]里内容,第二个关键字为默认值//会把<"hihi",0>放入if (mp["hihi"] == 4) cout << "hihi=4" << endl;else cout << "no" << endl;//begin/end:迭代器,用范围for遍历for (auto& [k, v] : mp){cout << k << "编号:" << v << endl;}//erase:删除,时间复杂度近似O(1)mp.erase("hihi");//find:查找元素,返回迭代器//count:查询元素出现次数,一般用来判断元素是否在哈希表中//时间复杂度都近似O(1)if(mp.count("lili")) cout << "yes" << endl;else cout << "no" << endl;//size:求哈希表元素个数//empty:判断哈希表是否为空//时间复杂度都近似O(1)cout << mp.size() << endl;if (mp.empty()) cout << "空" << endl;else cout << "非空" << endl;//存图test();
}

相关文章:

哈希表和STL —— unorderde_set/unordered_map【复习笔记】

1. 哈希表的相关概念 1.1 哈希表的定义 哈希表&#xff0c;又称为散列表&#xff0c;是根据关键字直接进行访问的数据结构。 它通过一个哈希函数&#xff08;Hash Function&#xff09;&#xff0c;建立了一种关键字和存储地址间的直接映射关系&#xff0c;将每个关键字映射…...

计算机毕业设计SpringBoot+Vue.js体育馆使用预约平台(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

42 session反序列化漏洞

参考资料&#xff1a;3. php反序列化从入门到放弃(入门篇) - bmjoker - 博客园 session文件上传漏洞利用原理 当在php.ini中设置session.upload_progress.enabled On的时候&#xff0c;PHP将能够跟踪上传单个文件的上传进度。当上传正在进行时&#xff0c;以及在将与session…...

【Jenkins】个人向-Jenkinsfile如何写

官方参考&#xff1a;https://www.jenkins.io/doc/book/pipeline/syntax/ Pipeline Utility Steps 插件&#xff1a;https://birdbook.com.cn/ops/ci/jenkins/plugins/pipeline%20utility%20steps.html 常用环境变量 含义表达式备注params&#xff0c;传入参数传入参数params…...

staruml绘制时序图和用例图

文章目录 1.文章介绍2.绘制用例图3.绘制时序图 1.文章介绍 之前&#xff0c;我们初步介绍了这个staruml软件的安装和如何使用这个软件对于uml类图进行绘制&#xff0c;当时我们是绘制了这个user类&#xff0c;实现了相关的接口&#xff0c;表示他们之间的关系&#xff0c;在今…...

问题修复-后端返给前端的时间展示错误

问题现象&#xff1a; 后端给前端返回的时间展示有问题。 需要按照yyyy-MM-dd HH:mm:ss 的形式展示 两种办法&#xff1a; 第一种 在实体类的属性上添加JsonFormat注解 第二种&#xff08;建议使用&#xff09; 扩展mvc框架中的消息转换器 代码&#xff1a; 因为配置类继…...

Rust配置开发环境+服务器实战

https://www.cnblogs.com/skzxc/p/12129353.html 默认已经安装好MSVC。 官网https://www.rust-lang.org/zh-CN/learn/get-started安装Rust安装器&#xff0c;选择winodwsx64版本 运行安装&#xff0c;将文件夹移动到D盘&#xff0c;安装后&#xff0c;文件夹在C:\Users\xxx下…...

使用DeepSeek+KIMI生成高质量PPT

一、使用DeepSeek DeepSeek官网&#xff1a;DeepSeek 点击“开始对话”&#xff0c;进入交互页面。 在上图中&#xff0c;输入问题&#xff0c;即可获取AI生成的结果。 基础模型&#xff08;V3&#xff09;&#xff1a;通用模型&#xff08;2024.12&#xff09;&#xff0c;高…...

虚拟机如何设置ip

在虚拟机中设置IP地址的具体步骤会因虚拟机软件&#xff08;如VMware、VirtualBox等&#xff09;和操作系统&#xff08;如Windows、Linux等&#xff09;的不同而有所差异。以下是几种常见虚拟机软件和操作系统的IP设置方法。 --- 一、VMware中的IP设置 1.Windows虚拟机 1. 打…...

蓝桥杯 路径之谜

路径之谜 题目描述 小明冒充 XX 星球的骑士&#xff0c;进入了一个奇怪的城堡。 城堡里边什么都没有&#xff0c;只有方形石头铺成的地面。 假设城堡地面是 nnnn 个方格。如下图所示。 按习俗&#xff0c;骑士要从西北角走到东南角。可以横向或纵向移动&#xff0c;但不能斜着走…...

Git操作指南:分支合并、回退及其他重要操作

在软件开发的协作过程中&#xff0c;Git 作为一款强大的版本控制系统&#xff0c;能帮助开发者高效管理代码的各个版本和分支。本文将详细介绍 Git 中常见的分支合并、取消本地修改、回退操作等&#xff0c;并提供通俗易懂的解释和步骤指南。 一、分支合并 分支合并是 Git 工…...

Element Plus中el-tree点击的节点字体变色加粗

el-tree标签设置 <el-tree class"tree":data"treeData":default-expand-all"true":highlight-current"true"node-click"onTreeNodeClick"><!-- 自定义节点内容&#xff0c;点击的节点字体变色加粗 --><!-- 动…...

jenkens使用笔记

jenkens使用笔记 笔记使用版本是2.492.1 git仓库ssh证书配置 已开始配置一直不行&#xff0c;然后下载插件&#xff0c;多次重启等一些列操作&#xff0c; 后来配置就可以工作了&#xff0c;原因不祥&#xff0c;不知道哪个配置起效了。 等回来闹明白了&#xff0c;再补充笔记…...

腾讯混元文生图大模型(Hunyuan-DiT)与Stable Diffusion(SD)对比分析

腾讯混元文生图大模型&#xff08;Hunyuan-DiT&#xff09;与Stable Diffusion&#xff08;SD&#xff09;对比分析 腾讯混元文生图大模型&#xff08;Hunyuan-DiT&#xff09;与Stable Diffusion&#xff08;SD&#xff09;作为当前文生图领域的两大代表模型&#xff0c;各自…...

深入浅出理解编译器:前端视角

一、编译器究竟是什么&#xff1f; 在前端开发的世界里&#xff0c;我们经常会听到 “编译器” 这个词。就拿 Babel 来说&#xff0c;在它的官网上&#xff0c;最显眼的一句话就是&#xff1a;“Babel is a JavaScript compiler”。那什么是 JavaScript 编译器呢&#xff1f;又…...

Minio搭建并在SpringBoot中使用完成用户头像的上传

Minio使用搭建并上传用户头像到服务器操作,学习笔记 Minio介绍 minio官网 MinIO是一个开源的分布式对象存储服务器&#xff0c;支持S3协议并且可以在多节点上实现数据的高可用和容错。它采用Go语言开发&#xff0c;拥有轻量级、高性能、易部署等特点&#xff0c;并且可以自由…...

Ubuntu系统上部署Node.js项目的完整流程

以下是在Ubuntu系统上部署Node.js项目的完整流程&#xff0c;分为系统初始化、环境配置、项目部署三个部分&#xff1a; 一、系统初始化 & 环境准备 bash # 1. 更新系统软件包 sudo apt update && sudo apt upgrade -y# 2. 安装基础工具 sudo apt install -y buil…...

DeepSeek效应初现:Grok-3补刀ChatGPT,OpenAI已在ICU?

嘿&#xff0c;技术小伙伴们&#xff01;今天咱们聊聊最近在AI界引发轰动的新闻——DeepSeek和xAI相继用R1和Grok-3证明了预训练Scaling Law并非OpenAI的护城河。这意味着什么呢&#xff1f;让我们一探究竟&#xff01; 开场白 首先&#xff0c;让我们看看最新的“全能冠军”…...

【知识】torchrun 与 torch.multiprocessing.spawn 的对比

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 来自ChatGPT、DeepSeek 有点干&#xff0c;可仅做了解。 torchrun 和 torch.multiprocessing.spawn 都是在 PyTorch 中用于并行化和分布式训练的工具&a…...

深入了解 K-Means 聚类算法:原理与应用

引言 在数据科学和机器学习的世界中&#xff0c;聚类是一项非常重要的技术&#xff0c;它帮助我们根据数据的相似性将数据划分为不同的组或簇。聚类算法在许多领域中得到了广泛的应用&#xff0c;如图像处理、市场细分、基因研究等。K-Means 聚类算法作为最常见的无监督学习算…...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

工业安全零事故的智能守护者:一体化AI智能安防平台

前言&#xff1a; 通过AI视觉技术&#xff0c;为船厂提供全面的安全监控解决方案&#xff0c;涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面&#xff0c;能够实现对应负责人反馈机制&#xff0c;并最终实现数据的统计报表。提升船厂…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

AtCoder 第409​场初级竞赛 A~E题解

A Conflict 【题目链接】 原题链接&#xff1a;A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串&#xff0c;只有在同时为 o 时输出 Yes 并结束程序&#xff0c;否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

Android15默认授权浮窗权限

我们经常有那种需求&#xff0c;客户需要定制的apk集成在ROM中&#xff0c;并且默认授予其【显示在其他应用的上层】权限&#xff0c;也就是我们常说的浮窗权限&#xff0c;那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...