从零带你底层实现unordered_map (1)
💯 博客内容:从零带你实现unordered_map
😀 作 者:陈大大陈
🚀 个人简介:一个正在努力学技术的准C++后端工程师,专注基础和实战分享 ,欢迎私信!
💖 欢迎大家:这里是CSDN,我总结知识和写笔记的地方,喜欢的话请三连,有问题请私信 😘 😘 😘
目录
超级容易踩坑的地方
unordered_map怎么实现
哈希冲突
开放寻址法
代码
unordered_map也就是哈希表,今天就来讲解它的用法。
unordered的意思是“无序”,这里强调了和map功能上的不同,因为map里面的东西是排好序的。
超级容易踩坑的地方
它是一个单向的迭代器。
为什么专门提到这个呢?因为这是我踩过坑的地方!!
单向迭代器压根就不能使用sort函数来排序!
std::unordered_map
的迭代器类型是ForwardIterator,而不是sort函数要求的RandomAccessIterator,这里不符合。
我们要排序的话,还是将unordered_map里存的值,转存到vector<pair>里面。
然后我们再自定义一个排序方法,对vector<pair>进行排序。
可参考下面的代码:
class Solution {
public:struct comp{bool operator()(const pair<string,int>&p1,const pair<string,int>&p2){return p1.second>p2.second||(p1.second==p2.second&&p1.first<p2.first);}};vector<string> topKFrequent(vector<string>& words, int k) {unordered_map<string,int> hash;for(auto &str:words) hash[str]++;vector<pair<string,int>> sortV(hash.begin(),hash.end());sort(sortV.begin(),sortV.end(),comp());vector<string> v;for(int i=0;i<k;i++){v.push_back(sortV[i].first);}return v;}
};
692. 前K个高频单词 - 力扣(LeetCode)
也可以使用std::set结构
对键进行排序,如下所示:
std::unordered_map<int, int> unordered;
std::set<int> keys;
for (auto& it : unordered) keys.insert(it.first);
for (auto& it : keys) {std::cout << unordered[it] << ' ';
}
unordered_map怎么实现
哈希冲突
hash也叫散列。
举一个例子,学校图书馆提供借书义务,怎么快速找到某个同学借的书?
我们可以引入一个关键值(日期),借书记录存的位置。
哈希和散列就是这样。
关键值和存储位置,建立一个关联关系。
如果值的跳跃很大,那空间就会很浪费。
有一个方法可以减少空间浪费,就是让数值统一对一个数取模。
但是这样就又会衍生出一个问题,就是哈希碰撞,也叫做哈希冲突。
例如,3对10取模是3,33对10取模也是3
这样一来,本来不同位置的两个值,现在映射到了相同的位置。
对于闭散列,我们有一个方法来解决这种情况。
开放寻址法
当前空间已经被占用,在开放空间里按照某种规则,再寻找一个未被占用的位置存储。
开放寻址法有两种方法。
1.线性探测 hashi+i (i>=0)
2.二次探测 hashi+i^2 (i>=0)
不需要担心后面找不到位置,因为有负载因子在控制。
负载因子是当前值的个数和空间的比率,它会保持在一个值一下。
到一定程度,就会引发扩容。
负载因子太大,冲突可能会增加,效率降低。
负载因子太小,冲突会变少,但是空间消耗会增大,空间利用率降低。
要底层实现哈希表,有一个很尴尬的问题。
我们不知道如何判断一个位置有没有存值。
因为find是碰到空就停止,假设我们删除了20,那20的位置变为空。
我们再想寻找21,22,就找不到了,因为find在20的位置就停止了。
所以,我们需要区分开两种情况,一个位置是被删除了而导致空,还是本来就是空。
假设是本来就是空,那我们到这个位置就可以停止查找,假设是被删除才导致的空,我们就继续查找下去。
知道查找到这个值,或者查找到空为止。
不能直接扩容,因为映射关系会改变。
要扩容的话,要直接新开一段空间,重新映射,再释放旧空间。
代价很大,但是没有别的方式。
最难想到的就是扩容,咱们就新开一段空间,复用一下插入函数。
最后用swap交换一下新旧空间的内容。
这样写的好处是,函数调用完成后会自动释放空间。
下面是第一版的代码,之后的补全版本代码会在接下来几个博客中发出来。
代码
#pragma once
#include<vector>
namespace bit
{enum Status{EMPTY,EXIST,DELETE};template<class T, class V>struct HashData{pair<K, V> _kv;Status _s;//状态};template<class T,class V>class HashTable{public:HashTable(){_tables.resize(10);}bool insert(const pair<K, V>& kv){if (_n*10 / _tables.size() == 0.7) //因为整形相除不可能是0.7,所以乘10,也可以转换成double{size_t NewSize = _tables.size() * 2;HashTable<K, V> newHT;newHT._tables.resize(NewSize);for (int i = 0; i < _tables.size(); i++){if (_tables[i]._s == EXIST){newHT.insert(_tables[i].kv);}}_tables.swap(newHT._tables);}size_t hashi = kv.first % _tables.size();while (_tables[hashi]._s == EXIST){++hashi;//当等于存在时,往后查找hashi %= _tables.size();//防止越界访问}_tables[hashi]._kv = kv;_tables[hashi]._s = EXIST;++_n;return true;}private:vector<HashData> _tables;size_t _n = 0;//存储的关键字的个数};
}
相关文章:
从零带你底层实现unordered_map (1)
💯 博客内容:从零带你实现unordered_map 😀 作 者:陈大大陈 🚀 个人简介:一个正在努力学技术的准C后端工程师,专注基础和实战分享 ,欢迎私信! 💖 欢迎大家…...

第六届浙江省大学生网络与信息安全竞赛 2023年 初赛/决赛 WEB方向 Writeup
-------------------【初赛】------------------- easy php 简单反序列化 __debuginfo()魔术方法打印所需调试信息,反序列化时候执行! 链子如下: BBB::__debuginfo()->CCC::__toString()->AAA::__call()EXP: <?php…...

设计模式篇---装饰模式
文章目录 概念结构实例总结 概念 装饰模式:动态的给一个对象增加一些额外的职责。就扩展功能而言,装饰模式提供了 一种比使用子类更加灵活的替代方案。 装饰模式是一种对象结构型模式,它以对客户透明的方式动态地给一个对象附加上更多的责任…...

JAXB:根据Java文件生成XML schema文件
说明 JAXB有个schemagen脚本,可以根据Java文件生成XML schema。这个工具在JAXB独立发布包中有,可以从官网下载JAXB的独立发布包: https://eclipse-ee4j.github.io/jaxb-ri/ 示例 使用schemagen -d <path> <java files>格式 …...

opencv(5): 滤波器
滤波的作用:一幅图像通过滤波器得到另一幅图像;其中滤波器又称为卷积核,滤波的过程称为卷积。 锐化:边缘变清晰 低通滤波(Low-pass Filtering): 目标:去除图像中的高频成分&#…...

《微信小程序开发从入门到实战》学习二十二
3.3 开发创建投票页面 3.3.10 使用switch开关组件 用switch开关组件增加一个设置是否匿名投票的功能。 switch常用属性如下: checked 开还是关,默认false关 disabled 是否禁用,默认false不禁用࿰…...
LLM模型-讯飞星火与百度文心api调用
spark-wenxin 1-讯飞星火1_1-SparkApi.py1_2- Chat_spark.py1_3-调用api 2-百度文心2_1.code 3-两者之间比较与openai 1-讯飞星火 进入讯飞官网进行创建应用,获取相关密钥APPID,APISecret,APIKey,选择最新版本 首次调用讯飞官方a…...

AIGC ChatGPT 4 将数据接口文件使用Python进行入库Mysql
数据分析,数据处理的过程,往往将采集到的数据,或者从生产库过来的接口文件,我们都需要进行入库操作。 如下图数据: 将这样的数据接口文件,进行入库,插入到Mysql数据库中。 用Python代码来完成。 ChatGPT4来完成代码输入。 ChatGPT4完整内容如下: 这个任务可以使用`…...

Loguru:一个超酷的Python库
在项目中,了解代码运行情况至关重要,特别是遇到Bug需要排除问题的时候,而这正是日志记录发挥作用的地方。对于Python开发者来说,Loguru是一个简单但功能强大的日志记录库,它使得跟踪代码的行为变得轻松而高效。 什么是…...
cloud的概念
"Cloud"(云)通常指的是云计算(cloud computing)领域。云计算是一种通过网络(通常是互联网)提供计算资源和服务的模型。这些计算资源包括计算能力、存储空间、数据库、网络、分析能力等。云计算模…...

物联网赋能:WIFI HaLow在无线连接中的优势
在探讨无线网络连接时,我们不难发现,WIFI已经成为我们日常生活中不可或缺的一部分,承载了半数以上的互联网流量,并在家庭、学校、娱乐场所等各种场合广泛应用。然而,尽管WIFI4、WIFI5和WIFI6等协议无处不在,…...

淘宝商品详情数据接口(Taobao.item_get)
淘宝商品详情接口是一种程序化的接口,允许开发者根据商品ID或商品链接,获取淘宝平台上的商品详细信息。通过这个接口,开发者可以方便地获取商品的标题、价格、销量、描述等数据,进而提供给用户进行展示和购买。 使用淘宝商品详情…...

视频剪辑方法:一键批量调整色调的高效技巧
在视频剪辑的过程中,色调调整是一项非常重要的工作。它能够改变影片的氛围、情感和视觉效果,更好地沉浸在影片的情境中。然而,对于许多视频剪辑师来说,批量调整色调是一项非常繁琐的任务,需要耗费大量的时间和精力。色…...

NAS层协议栈学习笔记
NAS(Non-Access Stratum)是无线网络中非接入层及包括移动性管理(MM)和会话管理(SM)协议 ,在5G(NR)系统中连接管理(Connection Management)用于建立和释放UE与AMF之间的控制面(CP)信令连接。 5G中移动性管理是通过NAS信令在UE与核心网之间进行交互的,连接…...
前端食堂技术周刊第 105 期:TS 5.3 RC、Vite 5.0、W3C 新任 CEO、有害的 Pinia 模式、2024 更快的 Web
美味值:🌟🌟🌟🌟🌟 口味:金桂普洱 食堂技术周刊仓库地址:https://github.com/Geekhyt/weekly 大家好,我是童欧巴。欢迎来到前端食堂技术周刊,我们先来看下…...
jenkins 使用原生 git clone 命令,指定ssh密钥文件
使用环境变量 GIT_SSH_COMMAND 从Git版本2.3.0可以使用环境变量GIT_SSH_COMMAND,如下所示: GIT_SSH_COMMAND"ssh -i ~/.ssh/id_rsa_example" git clone example请注意,-i有时可以被您的配置文件覆盖,在这种情况下&…...
cobol数据类型
数据类型 数据部(data division)是用来描述程序中使用的变量的。 data name 数据名称 数据名称必须在数据部中定义,才能在过程部中使用。必须有一个用户自定义的名称,不能使用关键字,为存储实际数据的存储单元提供引…...

Java Web——JS中的BOM
1. Web API概述 Web API 是指浏览器提供的一套接口,这些接口允许开发人员使用 JavaScript(JS)来操作浏览器功能和页面元素。通过 Web API,开发人员可以与浏览器进行交互,以实现更复杂的功能和效果。 1.1. 初识Web AP…...

三十分钟学会Hive
Hive的概念与运用 Hive 是一个构建在Hadoop 之上的数据分析工具(Hive 没有存储数据的能力,只有使用数据的能力),底层由 HDFS 来提供数据存储,可以将结构化的数据文件映射为一张数据库表,并且提供类似 SQL …...
云计算发展
云计算,作为当今信息技术领域的核心力量,正在快速推动着我们社会的数字化转型。从智能家居到无人驾驶,从虚拟现实到人工智能,云计算的应用无处不在,它不仅仅是一个技术概念,更是一种全新的生活方式。在这个…...
沉浸式 “飞进” 鸟巢:虚拟旅游新体验
(一)全方位视角探秘 开启鸟巢虚拟旅游,借助 VR 技术,能从任意角度欣赏其外观。高空俯瞰,独特的钢结构如精美编织画卷,钢梁交织,阳光下闪耀银光,与绿树、蓝天相衬。拉近镜头&#x…...

干泵,干式螺杆真空泵
干式真空泵: 无油干式机械真空泵(又简称干式机械泵)是指泵能从大气压力下开始抽气,又能将被抽气体直接排到大气中去,泵腔内无油或其他工作介质,而且泵的极限压力与油封式真空泵同等量级或者接近的机械真空泵…...

STM32G4 电机外设篇(二) VOFA + ADC + OPAMP
目录 一、STM32G4 电机外设篇(二) VOFA ADC OPAMP1 VOFA1.1 VOFA上位机显示波形 2 ADC2.1 用ADC规则组对板载电压和电位器进行采样 3 OPAMP(运放)3.1 结合STM32内部运放和ADC来完成对三相电流的采样3.2 运放电路分析 附学习参考…...
Realsense D435i 使用说明
D435i 驱动安装 及 ROS使用 Ubuntu16.04适配https://blog.csdn.net/lemonxiaoxiao/article/details/107834936 过程中遇到fatal error ; 需要添加标签。 使用下面网址的博客解决了。https://blog.csdn.net/xuzhengzhe/article/details/135407342 最终如下: target…...

第4讲、Odoo 18 模块系统源码全解与架构深度剖析【modules】
引言 Odoo 是一款强大的开源企业资源规划(ERP)与客户关系管理(CRM)系统,其核心竞争力之一在于高度模块化的架构设计。模块系统不仅是 Odoo 框架的基石,更是实现功能灵活扩展与定制的关键。本文将结合 Odoo…...

allWebPlugin中间件VLC专用版之截图功能介绍
背景 VLC控件原有接口具有视频截图方法,即video对象的takeSnapshot方法,但是该方法返回的是一个IPicture对象,不适合在谷歌等现代浏览器上使用。因此,本人增加一个新的视频截图方法takeSnapshot2B64方法,直接将视频截图…...

【目标检测】【ICCV 2021】条件式DETR实现快速训练收敛
Conditional DETR for Fast Training Convergence 条件式DETR实现快速训练收敛 代码链接 论文链接 摘要 最近提出的DETR方法将Transformer编码器-解码器架构应用于目标检测领域,并取得了显著性能。本文针对其训练收敛速度慢这一关键问题,提出了一种条…...

java虚拟机2
一、垃圾回收机制(GC) 1. 回收区域:GC主要回收堆内存区域。堆用于存放new出来的对象 。程序计数器、元数据区和栈一般不是GC回收的重点区域。 2. 回收单位:GC以对象为单位回收内存,而非字节。按对象维度回收更简便&am…...
vscode连接的linux服务器,上传项目至github
问题 已将项目整个文件夹拷贝到克隆下来的文件夹中,并添加了所有文件,并修改了commit -m,使用git push -u origin main提交的时候会出现vscode请求登录github,确定之后需要等待很久,也无果 原因 由于 远程服务器无法…...

kafka学习笔记(三、消费者Consumer使用教程——从指定位置消费)
1.简介 Kafka的poll()方法消费无法精准的掌握其消费的起始位置,auto.offset.reset参数也只能在比较粗粒度的指定消费方式。更细粒度的消费方式kafka提供了seek()方法可以指定位移消费允许消费者从特定位置(如固定偏移量、时间戳或分区首尾)开…...