C++_unordered系列关联式容器(哈希)

news2024/9/28 22:17:26

unordered系列关联式容器,我们曾在C++_map_set详解一文中浅浅的提了几句。今天我们来详细谈谈

本身在C++11之前是没有unordered系列关联式容器的,unordered系列与普通的map、set的核心功能重叠度达到了90%,他们最大的不同就是底层结构的不同,map和set的底层使用的是红黑树;unordered底层是用的hash结构,两者在使用上基本上没有什么不同,map和set使用方法那一套在unordered系列容器同样试用,这里不再赘述。本篇文章主要讨论一些哈希相关知识。

unordered系列与mapset的对比

unordered系列map和set
对key的要求不同支持key转成整形 + 比较相等支持比较大小
遍历遍历无序遍历有序
迭代器单向迭代器双向迭代器
性能差异(插入删除等)O(1)O(logN)
底层结构哈希结构红黑树

底层结构

哈希概念

在顺序结构以及平衡树中,元素关键码与其存储位置之间没有对应的关系,因此在查找一个元素时,必须要经过关键码的多次比较。所以顺序查找时间复杂度为O(N),平衡树中的时间复杂度为树的高度,即O(log N),搜索的效率取决于搜索过程中元素的比较次数。

在数组中,我们可以通过下标访问我们任何想访问的元素,即不经过任何比较,直接从表中得到要搜索的元素。如果构造出一种像数组一样的存储结构,通过某种函数(hashFunc)使元素的存储位置与它的关键码之间能够建立一一映射的关系,那么在查找时通过该函数可以很快找到该元素。

当向该结构中插入元素时:

根据待插入元素的关键码,以此函数计算出该元素的存储位置并按此位置进行存放;

当在该结构中搜索元素时:

对元素的关键码进行同样的计算,把求得的函数值当做元素的存储位置,在结构中按此位置取元素比较,若关键码相等,则搜索成功。

该方式即为哈希(散列)方法,哈希方法中使用的转换函数称为哈希(散列)函数,构造出来的结构称为哈希表(Hash Table)(或者称散列表)。

上面啰啰嗦嗦一大堆概念,其实一个例子就可以搞定:

我们将元素的值映射到一个数组相应的位置,用该方法进行搜索不必进行多次关键码的比较,因此搜索的速度比较快。

哈希函数

常见的哈希函数

1. 直接定址法

取关键字的某个线性函数为散列地址:Hash(Key)= A*Key + B

优点:简单、快

缺点:只适合范围相对集中的一组元素

2. 除留余数法

key模上一个表的大小 N 以后,在映射到表中的一个位置,hash(key) = key % N   (N是表的大小) <上例中使用的就是该方法>


我们再来思考一个问题:如果按照上述哈希方式,向集合中插入元素44,会出现什么问题?

如果插入44,即hash(44) = 44 % 10 = 4,与hash(4)映射到了相同的位置,也就是说一个位置映射了两个值,这种情况我们称为哈希冲突。

哈希冲突

对于两个数据元素的关键字 i j ,有 i != j ,但有:Hash(i) == Hash(j),即:不同关键字通过相同哈希哈数计算出相同的哈希地址,该种现象称为哈希冲突或哈希碰撞

哈希冲突的解决

解决哈希冲突两种常见的方法是:闭散列和开散列

闭散列

闭散列也叫开放定址法,当发生哈希冲突时,如果哈希表未被装满,说明在哈希表中必然还有空位置,那么可以把key存放到冲突位置中的“下一个” 空位置中去。就类似于大学上课,教室第一排的位置被占了,那我们可以选择第二排。现在的问题是如何找到下一个位置呢?

方法一:线性探测

从发生冲突的位置开始,依次向后探测,直到寻找到下一个空位置为止。

1. 通过哈希函数获取待插入元素在哈希表中的位置

2. 如果该位置中没有元素则直接插入新元素,如果该位置中有元素发生哈希冲突,使用线性探测找到下一个空位置,插入新元素

如上例中的插入元素44:


采用闭散列处理哈希冲突时,不能随便物理删除哈希表中已有的元素,若直接删除元素会影响其他元素的搜索。比如删除元素4,如果直接删除掉,44查找起来可能会受影响,因为线性探测的查找规则是,从冲突位置开始向后查找,直到遇到空为止。如果直接把4删掉,4所在的位置就变为了空,查找44的时候,在还未找到44的情况下就直接停止查找了。因此线性探测采用标记的伪删除法来删除一个元素。

虽然线性探测可以解决哈希冲突,但是如果所有的冲突连在一起,容易产生数据“堆积”,即:不同关键码占据了可利用的空位置,使得寻找某关键码的位置需要许多次比较,导致搜索效率降低。如何缓解这种情况呢?我们看方法二

方法二:二次探测

如果说线性探测是 当前位置 +1,+2,+3.....的方式去探测;那么二次探测就是 当前位置 +1^2,+2^2,+3^2......的方式探测。也就是说二测探测是跳跃着进行探测的,该方法有效的解决了冲突连在一起,产生的数据“堆积”问题。

开散列

开散列法又叫哈希桶(拉链法),首先对关键码集合用散列函数计算散列地址,具有相同地址的关键码归于同一子集合,每一个子集合称为一个桶,各个桶中的元素通过一个单链表链接起来,各链表的头结点存储在哈希表中。

从上图可以看出,开散列中每个桶中放的都是发生哈希冲突的元素。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2174933.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AVL树(平衡二叉树)的介绍以及相关构建

欢迎光临 &#xff1a; 羑悻的小杀马特-CSDN博客 目录 一AVL树的介绍&#xff1a; 二AVL树的实现&#xff1a; 1结构框架&#xff1a; 2节点的插入&#xff1a; 旋转&#xff1a; 21左单旋&#xff1a; 2.1.1左单旋介绍及步骤&#xff1a; 2.1.2左单旋代码实…

【JavaSE系列】IO流

目录 前言 一、IO流概述 二、IO流体系结构 三、File相关的流 1. FileInputStream 2. FileOutputStream 3. FileReader 4. FileWriter 四、缓冲流 五、转换流 1. InputStreamReader 2. OutputStreamWriter 六、数据流 七、对象流 八、打印流 九、标准输入输出流…

C++学习9.28

1> 创建一个新项目&#xff0c;将默认提供的程序都注释上意义 por QT core gui #QT表示引入的类库 core:核心库例如IO操作在该库中 gui:图形化显示库 #如果要使用其他类库中的相关函数&#xff0c;就需要调用相关类库后&#xff0c;才能加以使用greaterThan(Q…

c++926

1.什么是虚函数&#xff1f;什么是纯虚函数&#xff1f; 虚函数&#xff1a;被virtual关键字修饰的成员函数&#xff0c;用于实现多态性&#xff0c;通过基类访问派生类的函数。纯虚函数&#xff1a;在虚函数后面添加0&#xff0c;只有声明而没有实现&#xff0c;需要派生类提…

天龙八部怀旧单机微改人面桃花+安装教程+GM工具+虚拟机一键端

今天给大家带来一款单机游戏的架设&#xff1a;天龙八部怀旧单机微改人面桃花。 另外&#xff1a;本人承接各种游戏架设&#xff08;单机联网&#xff09; 本人为了学习和研究软件内含的设计思想和原理&#xff0c;带了架设教程仅供娱乐。 教程是本人亲自搭建成功的&#xf…

图说数集相等定义表明“R各元x的对应x+0.0001的全体=R“是几百年重大错误

黄小宁 设集A&#xff5b;x&#xff5d;表A各元均由x代表&#xff0c;&#xff5b;x&#xff5d;中变量x的变域是A。其余类推。因各数x可是数轴上点的坐标故x∈R变为实数yx1的几何意义可是&#xff1a;一维空间“管道”g内R轴上的质点x∈R(x是点的坐标)沿“管道”g平移变为点y…

红队信息搜集扫描使用

红队信息搜集扫描使用 红队行动中需要工具化一些常用攻击&#xff0c;所以学习一下 nmap 等的常规使用&#xff0c;提供灵感 nmap 帮助 nmap --help主机扫描 Scan and no port scan&#xff08;扫描但不端口扫描&#xff09;。-sn 在老版本中是 -sP&#xff0c;P的含义是 P…

视频美颜SDK与直播美颜工具API是什么?计算机视觉技术详解

今天&#xff0c;小编将深入探讨视频美颜SDK与直播美颜工具API的概念及其背后的计算机视觉技术。 一、视频美颜SDK的概念 视频美颜SDK是一套用于开发实时美颜效果的工具集&#xff0c;开发者可以利用它在视频流中实现面部特征的优化。这些SDK通常提供了一系列功能&#xff0c…

.NET 红队武器库和资源集合 (第38期)

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…

计算机网络自顶向下(1)---网络基础

目录 1.网络的分类 2.网络协议 3.网络分层结构 1.OSI七层模型 2.TCP/IP四层模型 3.网络与OS的关系 4.网络传输基本流程 1.协议报头 5.网络中的地址管理 1.IP地址 2.端口号 6.传输层协议 1.TCP协议 2.UDP协议 3.网络字节序 7.socket 1.网络的分类 局域网&…

excel-VBA知识点记录

1、计算机硬件的组成部分 内存&#xff0c;一旦断电&#xff0c;存储在里面的数据就消失了&#xff0c;而硬盘是永久存储数据的&#xff0c;所以刚开始我们在文件里面编辑没有按保存的时候&#xff0c;数据是在内存里面的&#xff0c;一旦断电数据就没了&#xff0c;但我们点了…

大语言模型知识点分享

1 目前主流的开源模型体系有哪些&#xff1f; Prefix Decoder 系列模型 核心点&#xff1a; 输入采用双向注意力机制&#xff0c;输出为单向注意力。双向注意力意味着输入的每个部分都可以关注到输入的所有其他部分&#xff0c;这在理解上下文时具有很强的优势。 代表模型&a…

六级翻译 高分笔记

第一节 句子的拆分与重组 核心原则&#xff1a;拆主干&#xff0c;补修饰 一、句子的拆分与重组 1.青藏铁路是世界最高最长的高原铁路。&#xff08;“的”字前面所有去掉&#xff0c;就是句子主干&#xff09; The Qinghai-Tibet Railway is the highest and longest plate…

css 数字比汉字要靠上

这个问题通常是由于数字字体的下排的问题造成的&#xff0c;也就是数字的底部边缘位置比汉字的顶部边缘位置更靠下。为了解决这个问题&#xff0c;可以尝试以下几种方法&#xff1a; 使用CSS的vertical-align属性来调整对齐方式。例如&#xff0c;可以将数字的对齐方式设置为to…

数组的练习

1.使用函数的递归方法&#xff0c;输出给定字符串的逆序&#xff0c;如"abcdefg"&#xff0c;输出为“gfedcba”. 方法一&#xff1a;首先不采用递归的方法&#xff0c;如何完成上述要求 #include<stdio.h> #include<string.h> int main() {char arr[]…

3.数据结构与算法-基本概念和术语

数据、数据元素、数据项和数据对象 数据 数据元素 学生表-记录 数-节点 图&#xff1a;顶点 数据项 数据对象 数据对象与数据元素的关系 数据结构 数据结构的三个部分 逻辑结构的种类 存储结构分类 顺序存储结构 链式存储结构 索引存储结构 散列存储结构 数据类型和抽象数据类…

Linux中的文件缓冲区

目录 使用 dup2 系统调用 为命令行解释器添加重定向功能 理解缓冲区问题 缓存区的刷新策略 FILE的本质 尝试封装C语言的FILE 小共识&#xff1a; cd->当前路径->当前进程的工作路径->工作路径可以被修改->每个进程都有当前路径->故cd改的是子进程的路径-…

算力共享平台的控制流程,业务流程

目录 控制流程 业务流程 在提供的计算机网络系统结构示意图和描述中,我们可以区分出控制流程和业务流程的组成部分。 控制流程 控制流程主要涉及系统内部的管理、调度和监控操作,以确保系统能够按照预定的规则和策略运行。在这个例子中,控制流程可能包括但不限于以下部分…

K8S真正删除pod

假设k8s的某个命名空间如&#xff08;default&#xff09;有一个运行nginx 的pod&#xff0c;而这个pod是以kubectl run pod命令运行的 1.错误示范&#xff1a; kubectl delete pod nginx-2756690723-hllbp 结果显示这个pod 是删除了&#xff0c;但k8s很快自动创建新的pod,但是…

【C++算法】5.双指针_乘最多水的容器

文章目录 题目链接&#xff1a;题目描述&#xff1a;解法C 算法代码&#xff1a;图解&#xff1a; 题目链接&#xff1a; 11.盛最多水的容器 题目描述&#xff1a; 解法 7x749 解法一&#xff1a;暴力枚举 输入&#xff1a;[1&#xff0c;8&#xff0c;6&#xff0c;2&#xf…