【C++、数据结构】哈希表——散列表(一)(概念/总结)

「前言」

🌈个人主页: 代码探秘者
🌈C语言专栏:C语言
🌈C++专栏: C++ / STL使用以及模拟实现
🌈数据结构专栏: 数据结构 / 十大排序算法
🌈Linux专栏: Linux系统编程 / Linux网络编程(准备更新)
🌈喜欢的诗句:天行健,君子以自强不息.

pic_8da49713.png

🥙1.散列表的基本概念

在这里插入图片描述

  • 散列表(哈希表,Hash Table):是⼀种数据结构。特点是:可以根据数据元素的关键字计算出它在散列表中的存储地址
  • 散列函数(哈希函数)Addr=H(key) 建⽴了“关键字”→“存储地址”的映射关系。

例:某散列表的⻓度为13,散列函数 H(key)=key%13。依次将数据元素 19、14、23 插⼊散列表:
在这里插入图片描述
19%13=6
14%13=1
23%13=10

理想情况下,在散列表中查找⼀个元素的时间复杂度为O1

  • 冲突:在散列表中插⼊⼀个数据元素时,需要根据关键字的值确定其存储地址,若该地址已经存储了其他元素,则称这种情况为“冲突(碰撞)
  • 同义词:若不同的关键字通过散列函数映射到同⼀个存储地址,则称它们为“同义词”
    *在这里插入图片描述
    关于冲突:
  • 减少冲突构造更适合的散列函数,让各个关键字尽可能地映射到不同的存储位置,从⽽减少“冲突”
  • 处理冲突拉链法、开放定址法(包含四种探测方法)

🥙2.散列函数的构造

1.散列函数定义

在这里插入图片描述

  • 散列函数(哈希函数)Addr=H(key) 建⽴了“关键字”→“存储地址”的映射关系。

2.设计散列函数注意点

设计散列函数时应该注意什么
在这里插入图片描述
在这里插入图片描述

3.常见的散列函数

1.除留余数法

  • 除留余数法 —— H(key) = key % p

  • 在这里插入图片描述

  • 散列表表⻓为m,取⼀个不⼤于m但最接近或等于m的质数p
    比如:m=15,15 不是素数,我找一个比它小的素数,13 或11
    在这里插入图片描述

p选质数的原因:

  • 原因:对质数取余,可以分布更均匀,从⽽减少冲突
    在这里插入图片描述

2.直接定址法

  • 直接定址法 —— H(key) = key 或 H(key) = a*key + b

在这里插入图片描述

  • 其中,a和b是常数。这种⽅法计算最简单,且不会产⽣冲突。若关键字分布不连续,空位较多,则会造成存储空间的浪费

在这里插入图片描述

3.数字分析法

  • 数字分析法 —— 选取数码分布较为均匀的若⼲位作为散列地址
  • 在这里插入图片描述

在这里插入图片描述

4.平⽅取中法

  • 平⽅取中法——取关键字的平⽅值的中间⼏位作为散列地址
  • 在这里插入图片描述
    在这里插入图片描述

4.总结

在这里插入图片描述

🥙3.处理冲突的方法

一.处理冲突-拉链法

在这里插入图片描述

  • 拉链法(⼜称链接法、链地址法):把所有同义词”存储在⼀个链表中。

在这里插入图片描述

1.插入操作

例:若散列表⻓度为13,散列函数 H(key)=key%13,⽤拉链法解决冲突。依次插⼊关键字 {19, 14, 23, 1, 68, 20, 84, 27, 55, 11, 10, 79}
在这里插入图片描述
如何在散列表(拉链法解决冲突)中插⼊⼀个新元素?

  • Step 1:结合散列函数计算新元素的散列地址
  • Step 2:将新元素插⼊散列地址对应的链表(可⽤头插法,也可⽤尾插法

在这里插入图片描述

2.插入操作的优化

  • 新元素插⼊链表时,若能保持链表有序,可以略微提⾼“查找”效率。
    在这里插入图片描述

3.查找元素

查找⻓度——在查找运算中,需要对⽐关键字的次数称为查找⻓度

  • 查找成功
    在这里插入图片描述
  • 查找失败
    在这里插入图片描述
    默认只统计关键字对比次数(空指针次数-部分才要求)
    在这里插入图片描述
    在这里插入图片描述

4.删除操作

  • 删除成功
    在这里插入图片描述
    在这里插入图片描述
  • 删除失败
    在这里插入图片描述

5.总结

在这里插入图片描述

二.处理冲突-开放定址法

在这里插入图片描述

  • 开放定址法:如果发⽣“冲突”,就给新元素找另⼀个空闲位置
  • 为什么叫“开放定址”?—— ⼀个散列地址,既对同义词开放,也对⾮同义词开放

在这里插入图片描述
探测方法:⽤什么规则确定“另⼀个空闲位置”

  • di 表示第 i 次发⽣冲突时,下⼀个探测地址与初始散列地址的相对偏移量。
    在这里插入图片描述

在这里插入图片描述

1.线性探测法

  • 插入操作
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

2.平⽅探测法(⼆次探测法)

在这里插入图片描述

3.双散列法

例:⻓度为13的散列表状态如下图所示,散列函数 H(key)=key%13,采⽤双散列法解决冲突,假设hash2(key)=13-(key %13)
分析:插⼊元素1、查找元素1 的过程。

在这里插入图片描述

  • 两个散列函数,第一个不行,开始使用第二个,计算di
    在这里插入图片描述

4.伪随机序列法

在这里插入图片描述
在这里插入图片描述

4.查找操作(统一)

查找操作原理类似,根据探测序列依次对⽐各存储单元内的关键字。

  • 若探测到⽬标关键字,则查找成功
  • 若探测到空单元,则查找失败

5.删除操作

如何删除⼀个元素:

  • Step 1:先根据散列函数算出散列地址,并对⽐关键字是否匹配。若匹配,则“查找成功”
  • Step 2:若关键字不匹配,则根据“探测序列”对⽐下⼀个地址的关键字,直到“查找成功”或“查找失败”
  • Step 3:若“查找成功”,则删除找到的元素

注:题⽬⼀定会说明具体是采⽤哪种探测序列(线性探测法、平⽅探测法、双散列法、伪随机序列法)

错误示范(注意-线性探测演示)

  • 先找15,删15
    在这里插入图片描述
  • 再要删1(开始探测了,会发现,找到原来放15的地方遇到空,这样就停止探测了)
    在这里插入图片描述

正确示范(逻辑删除)

  • 删15
    在这里插入图片描述
  • 找1
    在这里插入图片描述

注意

采⽤“开放定址法”(线性探测法、平⽅探测法、双散列法、伪随机序列法原)时,删除元素不能简单地将被删元素的空间置为空,否则将截断在它之后的探测路径,可以做⼀个“已删除”标记,进⾏逻辑删除

  • 逻辑删除定义一个flag=1, 删除则变0。(避免查找操作探测时,本来存在的数,没查到就停止探测了)。

在这里插入图片描述

6.总结

在这里插入图片描述

三.扩展:关于四种方法的探测覆盖率

线性探测法:采⽤线性探测法,⼀定可以探测到散列表的每个位置

  • 只要散列表中有空闲位置,就⼀定可以插⼊成功
  • 理想情况下,若散列表表⻓=m,则最多发⽣ m-1 次冲突即可“探测”完整个散列表

平⽅探测法:采⽤平⽅探测法,⾄少可以探测到散列表中⼀半的位置
在这里插入图片描述

  • 即便散列表中有空闲位置,也未必能插⼊成功
  • 若散列表⻓度 m 是⼀个可以表示成4j + 3的素数(如 7、11、19),平⽅探测法就能探测到所有位置

双散列法未必能探测到散列表的所有位置

  • 双散列法的探测覆盖率取决于第⼆个散列函数hash2(key) 设计的是否合理

  • hash2(key) 计算得到的值与散列表表⻓m互质,就能保证双散列发可以探测所有单元
    在这里插入图片描述

伪随机序列法:di 是⼀个伪随机序列,由程序员⼈为设计

  • 采⽤伪随机序列法,是否能探测到散列表中全部位置,取决于伪随机序列的设计是否合理

总结

在这里插入图片描述

🥙4.模拟实现哈希表

点击这里!

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

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

相关文章

OpenCV图像预处理1

目录 图像翻转 图像仿射变换 仿射变换函数 图像旋转 图像平移 图像缩放 图像倾斜 图像色彩空间转换 RGB 转 Gray RGB 转 HSV 图像二值化处理 图像掩模 图像位与操作 图像检测轮廓 绘制轮廓 图像翻转 cv2.flip(src, flipCode[, dst]) -> dst 用于翻转图像。翻…

金融量化交易模型的探索与发展

在当代金融市场中,量化交易模型的应用不断提升,逐渐成为大数据与人工智能等前沿技术的集大成者。量化交易借助数学模型和算法分析市场信息,自动执行交易决策,具备精确、效率高等特点,且能够在复杂多变的市场中有效应对…

求逻辑地址的页号和物理地址

逻辑地址空间按字编址 -->逻辑地址长度为:log2(逻辑地址空间) 页的大小 --> 页内偏移量占log(页的大小) 逻辑页号页内偏移量逻辑地址长度 因此假如一个逻辑地址空间为64kb,页的大小为1kb,逻辑地址为17CAH,求逻辑地址页号…

ETLCloud怎么样?深度解析其在数据管理中的表现

在BI或数据大屏等数据分析工具中,经常需要从多个业务系统中提取原始数据,然后对数据进行清洗、处理,以获取高质量、有效且干净的数据以供后续的BI进行数据统计和分析使用,从高质量的实现企业数据的价值变现。 然而,在…

Windows SEH异常处理讨论

Windows C程序异常的类型 在Windows C异常的场景中,我们需要理解以下两种类型的异常: C语言抛出的异常。 这是利用C throw抛出的exception,利用C try-catch即可捕获。即便是来自于另一个DLL的C exception,仍然能利用C try-catch…

Windows 基础(一):深入理解Windows,掌握命令行与Shell

内容预览 ≧∀≦ゞ Windows 基础(一)声明导语一、Windows 和 Linux 的区别二、Windows 的ShellShell 和 终端 的区别1. 命令提示符(CMD)2. Windows PowerShell3. Windows Terminal4. Windows Subsystem for Linux (WSL) 三、Windo…

【数据库系统概论】第3章 关系数据库标准语言SQL(一)数据查询(超详细)

目录 一、单表查询 1. 简单的数据查询 (1)选择表中若干列 (2)选择表中若干行(元祖) 2. 聚合函数与分组查询 聚集函数 GROUP BY分组查询 二、联接查询 1、连接概述 2. 内联接(INNER JO…

unity后端kbengine用DOTween让 移动同步丝滑

unity在网络同步kbengine框架,同步移动时, 看自己很丝滑,但看他人是在跳越移动,一闪一闪,像掉帧, 看什么插值,高频同步,都不实用 用DOTween的 transform.DOMove(目标位置, 时间); //顺滑移动动画 这段代码不是放在Avatar.cs,放在AvatarView.cs里 if (Avatar.isPlayer() false…

【Effective C++】阅读笔记3

1. 成员变量声明为Private 建议将成员变量声明为Private,然后再public中提供调用该数据的接口 设置成Private的原因分析 类内成员变量被声明为Private,那么就可以外部代码直接访问或者修改内部数据通过公共接口获取内部数据,这样可以减少对外…

CSS3新增背景属性(四)

CSS3新增背景属性 1 background-origin 设置背景图原点起始位置: padding-box:默认值从padding区域开始显示背景图像;border-box:从border区域开始显示背景图像;content-box:从content区域开始显示背景图像…

C语言中的main函数:命令行参数的工作原理

在C语言中,main函数是程序的入口点。它不仅可以接受返回值,还能处理命令行参数,允许用户在运行程序时传递数据。命令行参数是用户在启动程序时通过命令行界面提供的输入。C语言允许通过main函数的参数来访问这些输入。   int main(int argc…

我在命令行下学日语

同一个动作重复 300 遍,肌肉就会有记忆,重复 600 遍,脊柱就会有记忆,学完五十音图不熟练,经常遗忘或者要好几秒才想得起来一个怎么办?没关系,我做了个命令行下的小游戏 KanaQuiz 来帮助你记忆&a…

c++:vector

一、vector是什么? 1.1 vector的介绍 vector是表示可变大小数组的序列容器。 就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是…

一键切换暗黑模式,这些代码片段你不可错过

文章目录 前言正文1.多主题切换2.使用 SASS 实现轻松深色模式3.动画切换浅色与深色模式4.纯 CSS 主题切换5.GitHub 风格的深色模式切换6.持久深色模式7.基本 Vue 响应式切换8.创意灯泡切换 总结 前言 如今,许多网站设计师都会为用户提供浅色和深色模式的选择。这不…

理解为什么要有C++设计模式

什么时设计模式? 每一个模式描述了一个在我们周围不断重复的问题以及该问题的解决方案的核心,这样,就能一次有一次地使用该方案,而不必做重复劳动。 如何解决复杂性? 分解:人们面对复杂性有一个常见的做法…

HJ33 整数与IP地址间的转换

HJ33 整数与IP地址间的转换 整数与IP地址间的转换 描述 原理:ip地址的每段可以看成是一个0-255的整数,把每段拆分成一个二进制形式组合起来,然后把这个二进制数转变成 一个长整数。 举例:一个ip地址为10.0.3.193 每段数字 …

雷军救WPS“三次”,WPS注入新生力量,不再“抄袭”微软

救WPS“三次” 1989年,求伯君用128万行代码编写出了WPS1.0,宣告了中国自主办公时代的开启。 那时候,雷军还在武汉大学深造,他早就把求伯君当成了自己的榜样,这一来二去的,雷军和WPS之间也就结下了不解之缘…

[MySQL#10] 索引底层(1) | Page | 页目录

目录 1. 初识索引 2. 认识磁盘 3. MySQL与磁盘交互基本单位 4. 索引的理解 1. 重谈Page 2. 为什么IO交互要用Page 3. 有主键的表插入数据时的排序 4. 单个Page与多个Page 4.1 单个Page 4.2 多个Page 目录 单Page目录 多Page目录 在看本文之前,可以回顾…

sklearn 实现随机森林分类器 - python 实现

python sklearn 实现随机森林分类器 from sklearn.ensemble import RandomForestClassifier from sklearn.datasets import load_iris # 加载数据集 irisload_iris() x,yiris.data,iris.target print("x y shape:",x.shape,y.shape) # 创建并训练模型 model Random…

Altium Designer使用技巧(二)

一、创建类 1、按DC键,打开对象类。 2、右键添加一个类。命名为PWR。 3、将所有的电源类,全部添加到新创建的类中,从非成员类中点选到成员类中。 4、右下角点panes ,点PCB。 5、然后在左边单击PWR,点连接,可显示或…