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

数据结构(邓俊辉)学习笔记】词典 03—— 排解冲突(1)

文章目录

  • 1. 一山二虎
  • 2. 泾渭分明
  • 3. 开放定址
  • 4. 线性试探
  • 5. 赖惰删除

1. 一山二虎

在这里插入图片描述
此前我们已经多次指出,对于需要动态维护的散列表冲突是不可避免的,无论你的散列函数设计的有多么精妙,因此我们不得不回答的第二个重要问题就是一旦发生冲突,我们应该如何加以排解?

当然任何一种可行的排解方法都应该是在事先就约定好的预案。

所谓冲突,形象地说也就是一山不容二虎。那么倘若的确有两只老虎呢?用铁丝网将这座山分成两部分,两只老虎各居一侧。这种思路也就是所谓的多槽位法。如果此前的桶单员对应于山,那么每一个 slot 就对应于在这个山中用铁丝网分割出的一个子区域。

在这幅图中,如果这是散列表,那么这就是一个又一个的桶单元。在这里我们将每个桶单元都继续细分为 a、b、c、d 四个槽位。每个桶内部的这些槽位就可以用来存放彼此冲突的若干个词条。

在这里插入图片描述

比如这就是一个长度为 23 的散列表,其中每一个桶都被分成了三个槽位。现在我们依次将24个词条插入其中。

可以看到这里,尽管有些词条的确会彼此冲突,但依然可以在对应的桶中和平共处。当然,查找过程需要多出一步,除了需要根据关键码确定对应的统单元地址,还需要在桶中遍历所有的槽位,直到找到目标或者失败。

当然,只要每个桶中槽位的总数能够控制在常数以内,整体的查找效率就不会有实质的降低。

不过这种方法的缺点也是显而易见的,你能看得出来吗?是的,每一桶具体应该细分为多少个槽位?在事先几乎是无法预测的。如果分得过细,就会造成空间上的浪费。而反过来,无论你分得多细,在极端情况下仍有可能在某个特定的桶中发生大规模的冲突。那么面临这一两难的抉择如何破解呢?

2. 泾渭分明

在这里插入图片描述
多槽位法在空间效率和时间效率之间的两难处境?我们在学习向量时也曾遇到过,还记得那时的解决办法吗?是的,改用列表。

新的策略,如这幅图(上图)所示,如果这是整个桶数组,那么其中每一个单元都将各自拥有一个对应的列表。而每一个列表都可以用来存放一组彼此冲突的词条。是的,将相互冲突的词条串接起来,也就是所谓的 separate chaining。

在这里插入图片描述
来看独立链法的一个实例,依然是一个长度为23的散列表。接下来我们将64个词条插入其中。请留意观察每个桶所对应的列表是如何演化的。
~  
相对于与多槽位法独立链法的优势非常明显,比如除了最初的空链表,我们无需预留任何更多的空间。而且表的长度可以根据需要自由的伸缩。只要系统的资源足够,任意多次的冲突都可以解决。

得益于此前对 List 结构的良好封装,我们只需寥寥几句即可实现相应的散列表结构。当然,这种方法的缺点也同样是很明显的。比如这里需要引入额外的指针,而为了生成或销毁节点也需要借助动态内存的申请,相对于常规的操作,此类动态申请操作的时间成本大致要高出两个数量级。

然而这种方法最大的缺陷还不仅于此,你能发现吗?是的,系统的缓存功能。在这里,每桶内部的查找都是沿着对应的列表顺序进行的。然而在此之前,不同列表中各节点的插入和销毁次序完全是随机的。比如可能会是这样(上图中的黄色线条)。

因此,对于任何一个列表而言,其中的节点在物理空间上往往不是连续分布。因此系统很难预测你的访问方向,无法通过有效的缓存加速查找过程。当散列表的规模非常之大,以至于不得不借助 IO 时,这一矛盾就显得更加突出了。 那么为了有效的激活并充分利用系统的缓存功能,我们又当如何继续改进呢?

3. 开放定址

在这里插入图片描述
反观独立链法,其采用的是所谓封闭定址策略 closed addressing。也就是说,对于散列表中的任何一个单元,在其所对应的列表中能够存放,而且只能够存放那些与这个桶单元的地址,比如 k ,相冲突的词条。

也就是说每个词条应该属于哪个桶所对应的列表都是在事先已经注定了的。不难理解,只要采用这种策略,就很难保证每组冲突的词条在空间上能够彼此毗邻。 因此后续我们应该放弃这种策略并反其道而行之,也就是采用所谓的开放定址策略 open addressing。

这种策略的特点是散列表所占用的空间在物理上始终是地址连续的一块,相应的所有的冲突都在这块连续的空间中加以排解,而无需向独立链法那样申请额外的空间。没错,所有的散列以及冲突排解都在这样一块封闭的空间内完成。

因此相应的这种策略也可以称作为闭散列 closed hashing。既然是闭散列,那么每一个桶单元都应该面向所有可能的词条开放。也就是说在特定的情况下,每一个词条都有可能存放在任何一个桶中。

当然对于每一个特定的词条具体存放在哪个桶中是有不同的优先级的。其中优先级最高的自然是它本来就应该归属的那个桶。从这个桶开始,所有的桶都按照某种优先级关系排成一个序列。

而在查找对应的词条时,我们也总是从这个序列的起点出发,顺次去尝试每一个桶单元。每个词条所对应的这样一个序列,也称作试探序列、试探链或者查找链。当然,沿查找链的查找,同样有两种结果,或者在某一个特定的桶中找到目标元素,也就是所谓的成功,或者一旦抵达第一个空桶即可报告失败。

那么具体的应该如何来约定查找链呢?

4. 线性试探

在这里插入图片描述

查找链的第一种组织方法就是所谓的线性试探。具体来说,所谓的 linear probing 就是一旦发生冲突之后,我们会转而去试探它的后继,后继的后继,以及后继的后继的后继,诸如此类。同样的,最终可能会因为发现目标而报告成功,或者因为抵达某个空桶,而说明查找失败。

可以看到,在如此形势的散列表中,除了数据词条,无需任何附加空间。

而更重要的是,每一查找链都集中在某一局部。因此系统的缓存作用将得到充分的发挥,而对于大规模的数据集,如此更可以有效地减少 IO。当然,这种策略同样也具有它的弱点。

其中重要一点就是为了消除以往的冲突,可能会导致后续发生更多的冲突。来看这样一个实例,考察一个长度为7的散列表。

在这里插入图片描述
假设我们需要插入的是 0 1 2 3 7 这样 5 个词条,如果就按照这种顺序依次插入,那么首先是0就位,1 就位,2 和3 也相继就位。为了插入最后的7,我们首先去试探 0 号单元,结果发现它非空,为了排解这一冲突,我们会转而试探它的后继,也就是 1 号单元,情况一样,进而去试探 2 号 3号单元,直到最终在4号单元发现一个空桶,从而将7安置在这个桶中。在这个散列表的生命期内发生冲突的只有一个词条,也就是7。
~  
现在再来看另一插入次序,比如将 7 调整到最前端,首先插入它,我们依然开始于一个空的散列表。按照约定的次序,首先将 7 安置在0号桶,没有冲突。既然0号单元已被占用,所以接下来插入 0 必然发生一次冲突,并经过一次试探,最终将 0 安置在 1 号单元。至此1号桶也会被占用。因此接下来词条 1 的插入也会发生一次冲突,并最终将它安置在 2 号桶。这样的故事还会发生多次,具体的也需要在这个位置发现一次冲突之后,再将词条2存入到3号桶,最后依然要经过一次冲突,才能将词条 3 存入 4 号桶。在整个这样的过程中,词条0、词条1 2和3都发生了冲突。前后对比不难发现后一种插入序列所对应的很多冲突本来的确是可以不必发生的。

5. 赖惰删除

在这里插入图片描述

以线性试探为代表的开放定址策略在使用时若要支持词条的删除,则需格外的小心。我们来就此做一探讨。按照这种策略先后插入彼此冲突的一组词条都将存放在同一个查找序列中。而更确切地讲,他们应该按照逻辑次序构成整个查找链的一个前缀,其中不得有任何的空桶缝隙。

因此词条的删除操作需要做额外的一些处理。反之如果直接将词条删除,那么被删除的词条所留下的空桶就有可能将查找链切断,从而导致在此之后的词条丢失掉。尽管他们的确存在于散列表中,却如何也访问不到。

针对这一问题,一种简明的方法就是所谓的懒惰删除 lazy removal。也就是说如果在某个桶中此前曾有一个词条,那么在这个词条被删除之后,我们并不是简单地将这个桶清空,而是为其做上一个特殊的标记,比如说R,在这样一个桶所属的每一条查找链中,这类桶单元将根据具体情况可能扮演两种角色。

如果是针对某一特定词条的查找,那么在抵达这个桶时,根据这个标志我们就知道不应该在此中断,而因越过它继续查找下去。反过来,如果我们是为了插入新的词条而寻找一个空桶,那么在首次抵达带有这样一个标志的桶之后,就可以将它等效的视作是一个空桶,并将待插入的新词条径直的插入其中。
在这里插入图片描述

应该说针对开放定制策略,懒度删除不仅是不得已而为之的方法,也甚至可以说是针对这种情况的最优方法。因为毕竟在开放定址策略中,每一个同单元都同时属于多个查找链。

相关文章:

数据结构(邓俊辉)学习笔记】词典 03—— 排解冲突(1)

文章目录 1. 一山二虎2. 泾渭分明3. 开放定址4. 线性试探5. 赖惰删除 1. 一山二虎 此前我们已经多次指出,对于需要动态维护的散列表冲突是不可避免的,无论你的散列函数设计的有多么精妙,因此我们不得不回答的第二个重要问题就是一旦发生冲突&…...

HTML5+CSS3-HTML5入门

1.web标准 W3C为web标准化做出了以下事项,主要包括结构,表现和行为。 结构用于对网页的信息进行分类和整理,使用技术包括HTML,XML,XHTML 表现指网页的外在样式,一般包括网页的版式,颜色,字体&#xff0c…...

谷粒商城实战笔记-138-商城业务-首页-渲染二级三级分类数据

本节的主要内容是在前一节的基础上,提供结构查询出所有的二级、三级分类数据。 一,构造响应体数据结构 后端返回给前端的数据结构是在开发详细设计中应该确定的内容。 分析前端需要的数据结构,后端要将所有一级分类包含的二级和三级分类信…...

git的基础用法

文章目录 前言关联仓库提交代码分支操作账号免密 前言 记录一下git的一些基础用法。 关联仓库 # 初始化 git init# 关联仓库 git remote add origin <仓库地址># 查看当前关联的仓库 git remote -v# 一次只能remote一个&#xff0c;要换需要先删原来的 git remote rem…...

常见中间件漏洞(四、Apache合集)

目录 四、Apache 4.1 CVE-2021-41773 漏洞简介 影响版本 环境搭建 漏洞复现 四、Apache 4.1 CVE-2021-41773 Apache HTTP Server 路径穿越漏洞 漏洞简介 该漏洞是由于Apache HTTP Server 2.4.49版本存在目录穿越漏洞,在路径穿越目录<Directory/>Require all gra…...

HCIE-学习笔记

动态授权加入的成员优先级高于静态绑定的成员&#xff1b; any组&#xff08;缺省&#xff09;&#xff1a;所有用户或资源&#xff0c;通常用来配置默认规则。any组只能做目的组&#xff0c;不支持配置为源组。 同一个安全组既可以与多条授权规则绑定来表示动态用户&#xff0…...

【计算机网络】性能指标-带宽和时延(MB、GB、KB、B、byte、bit、Mb/s、Gb/s、b/s等)学习

文章目录 1、单位换算MB、b/s1.1 在计算机领域&#xff0c;大写的B、K、M、G表示1.2 在通信领域&#xff0c;小写的k代表的是1000,不是1024&#xff0c;转换的时候要注意区分 2、带宽3、时延&#xff08;时间消耗&#xff09;4、时延带宽积5、往返时延RTT 1、单位换算MB、b/s …...

ANN(Approximate Nearest Neighbor)搜索和索引库到底是什么?

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ ANN&#xff08;Approximate Nearest Neighbor&#xff09;搜索&#xff1a;最近邻搜索是一种在大规模数据集中快速找到与给定查询数据点距离最近的点的算法。与传统的精确最近邻搜索算法相比&#xff…...

勒索软件、供应链攻击等带来的思考!

2023年勒索软件、供应链攻击、地缘政治冲突与黑客活动主义、国家黑客间谍与APT组织活动成为网络安全的热点话题&#xff0c;生成式人工智能技术的武器化更是给动荡的全球网络安全威胁态势增加了不确定性、不对称性和复杂性。 即将到来的2024年&#xff0c;随着网络犯罪的规模化…...

【Nuxt】自定义插件和生命周期

自定义插件 方式一&#xff1a; app.vue // 创建插件(在app.vue中创建全局可以使用 而在某个页面中创建只有该页面可以使用) // 方式一&#xff1a; const nuxtApp useNuxtApp(); nuxtApp.provide("formDate", () > {return "2023-12-12"; }) nuxtAp…...

MySQL的简单介绍

文章目录 数据库关系型数据库非关系型数据”数据库的概念和用途MySQL数据库服务器、数据库和表的关系数据库的创建和删除表创建表修改常见的数据类型和约束字符串类型日期和时间类型PRIMARY KEY使用AUTO_INCREMENT使用UNIQUE使用FOREIGN KEY使用 SQL语言基础SQL语言简介SQL分类…...

leetcode 116.填充每个节点的下一个右侧结点指针

1.题目要求: 给定一个二叉树&#xff1a;struct Node {int val;Node *left;Node *right;Node *next; } 填充它的每个 next 指针&#xff0c;让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点&#xff0c;则将 next 指针设置为 NULL 。初始状态下&#xff0c;所有 ne…...

『 Linux 』网络基础

文章目录 协议分层OSI 七层模型TCP/IP 四层(五层)模型网络协议栈与操作系统的联系报文TCP/IP 通讯过程以太网通信的过程以太网的数据碰撞 协议分层 协议分层是计算机网络中奖网络协议进行组织和管理的方法; 通过将网络通信过程分成多个层次,每个层次负责特定的功能从而简化网络…...

Python酷库之旅-第三方库Pandas(070)

目录 一、用法精讲 281、pandas.Series.dt.daysinmonth属性 281-1、语法 281-2、参数 281-3、功能 281-4、返回值 281-5、说明 281-6、用法 281-6-1、数据准备 281-6-2、代码示例 281-6-3、结果输出 282、pandas.Series.dt.tz属性 282-1、语法 282-2、参数 282-…...

第一篇Linux介绍

目录 1、操作系统 2、Windows和Linux操作系统的区别 3、 Linux 的发行版本 4、 linux 分支 5、 Linux 的含义 6、Linux 特点 1、操作系统 常见操作系统有&#xff1a;Windows、MacOS、Unix/Linux。 类 UNIX Windows&#xff1a;其是微软公司研发的收费操作系统&#xff…...

在Windows编程中,MFC\C++中OnCopyData如何传递基础类型数据?

在C中&#xff0c;OnCopyData 并不是一个标准的C库或框架中的成员函数&#xff0c;它更常见于Windows编程中&#xff0c;特别是使用Win32 API或MFC&#xff08;Microsoft Foundation Classes&#xff09;时。OnCopyData 是一个在MFC应用程序中常用于处理来自其他应用程序的WM_C…...

10款超好用的图纸加密软件推荐,2024企业常用图纸加密软件分享

在现代企业中&#xff0c;设计图纸和敏感数据的安全性至关重要。一旦图纸泄露&#xff0c;可能会对企业造成不可估量的损失。因此&#xff0c;选择一款高效、可靠的图纸加密软件显得尤为重要。 1. 安秉图纸加密软件 安秉图纸加密软件是一款专为保护工程图纸和设计文件安全的软…...

BUUCTF [安洵杯 2019]easy_serialize_php 1

打开题目&#xff0c;看到一串php代码&#xff0c;试着代码审计一下&#xff0c;看一下有用信息 可以看出是通过$_SESSION[img]来读取文件 extract可以将数组中的变量导入当前变量表 也就是说我们可以伪造$_SESSION 数组中的所有数据 这里传递一个参数fphpinfo 先用hackbar进…...

前端面试宝典【CSS篇】【5】

在前端开发的世界里,每一次面试都是一次机遇,也是一次挑战。 你是否曾因技术深度不够而错失良机? 或是面对最新的技术趋势感到迷茫? 我们的【前端面试宝典】正是为此而来。 由拥有多年一线实战经验的资深工程师亲自授课,结合最新的行业动态与实战案例,旨在全面提升你的技…...

stem32江科大自学笔记

江科大B站教程连接:【STM32入门教程-2023版 细致讲解 中文字幕】 系列文章目录 提示&#xff1a;收集stem32江科大自学笔记&#xff0c;方便自己和他人查看 视频对应目录STM32入门教程P1-3 [1-2]&[2-1]1.STM32简介、系统介绍、软件安装P4 [2-2]2.基于标准库&#xff08;库…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

三维GIS开发cesium智慧地铁教程(5)Cesium相机控制

一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点&#xff1a; 路径验证&#xff1a;确保相对路径.…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

Nuxt.js 中的路由配置详解

Nuxt.js 通过其内置的路由系统简化了应用的路由配置&#xff0c;使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心&#xff0c;JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例&#xff1a; 1. onclick - 点击事件 当元素被单击时触发&#xff08;左键点击&#xff09; button.onclick function() {alert("按钮被点击了&#xff01;&…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...