算法基础—哈希表散列表的构建和处理冲突

一文搞定哈希(六种构建、四种冲突解决方法、查找算法总结) 写在前面:博主是一位普普通通的19届双非软工在读生,平时最大的爱好就是听听歌,逛逛B站。博主很喜欢的一句话花开堪折直须折,莫待无花空折枝:博主的理解是头一次为人,就应该做自己想做的事,做自己不后悔的事,做自己以后不会留有遗憾的事,做自己觉得有意义的事,不浪费这大好的青春年华。博主写博客目的是记录所学到的知识并方便自己复习,在记录知识的同时获得部分浏览量,得到更多人的认可,满足小小的成就感,同时在写博客的途中结交更多志同道合的朋友,让自己在技术的路上并不孤单。 目录: 1.哈希表的构建 2.哈希函数的. 阅读详情

1 哈希表的构建

1. 直接寻址法

取关键字或者关键字的某个线性函数值作为哈希地址,即H(Key)=Key或者H(Key)=a*Key+b(a,b为整数),这种散列函数也叫做自身函数.如果H(Key)的哈希地址上已经有值了,那么就往下一个位置找,知道找到H(Key)的位置没有值了就把元素放进去.

2. 数字分析法

分析一组数据,比如一组员工的出生年月,这时我们发现出生年月的前几位数字一般都相同,因此,出现冲突的概率就会很大,但是我们发现年月日的后几位表示月份和具体日期的数字差别很大,如果利用后面的几位数字来构造散列地址,则冲突的几率则会明显降低.因此数字分析法就是找出数字的规律,尽可能利用这些数据来构造冲突几率较低的散列地址.

3. 平方取中法

取关键字平方后的中间几位作为散列地址.一个数的平方值的中间几位和数的每一位都有关。因此,有平方取中法得到的哈希地址同关键字的每一位都有关,是的哈希地址具有较好的分散性。该方法适用于关键字中的每一位取值都不够分散或者较分散的位数小于哈希地址所需要的位数的情况。

4. 折叠法

折叠法即将关键字分割成位数相同的几部分,最后一部分位数可以不同,然后取这几部分的叠加和(注意:叠加和时去除进位)作为散列地址.数位叠加可以有移位叠加和间界叠加两种方法.移位叠加是将分割后的每一部分的最低位对齐,然后相加;间界叠加是从一端向另一端沿分割界来回折叠,然后对齐相加.

5. 随机数法

选择一个随机数,去关键字的随机值作为散列地址,通常用于关键字长度不同的场合.

6. 除留余数法

取关键字被某个不大于散列表表长m的数p除后所得的余数为散列地址.即H(Key)=Key MOD p,p<=m.不仅可以对关键字直接取模,也可在折叠、平方取中等运算之后取模。对p的选择很重要,一般取素数或m,若p选得不好,则很容易产生冲突。一般p取值为表的长度tableSize。

2 哈希表的冲突处理

何为哈希碰撞:
如果有两个数的余数相等,那么我的存储位置就会是在哈希表中的同一个下标之下,我们称这种情况为哈希碰撞。

2.1 开放地址法

开放地址法的基本思想是:有冲突的时候就去寻找下一个空的散列表地址,只要散列表足够大,空的散列地址总能找到,并将数据元素存入

除留余数法 Hi=(\mathrm{H}_{\mathrm{i}}=\left(\right.Hi​=( Hash(key) +di)\left.+\mathrm{d}_{\mathrm{i}}\right)+di​) mod mmm
did_idi​ 为增量序列

线性探测法

线性探测法的基本思想是,假定哈希函数为_H_(key),哈希表的地址区间长度为_m_,并将哈希表看成是一个循环空间,则线性探测法的探测地址序列可表示为

di\mathrm{d}_{\mathrm{i}}di​ 为 1,2,…m−11,2, \ldots \mathrm{m}-11,2,…m−1

用线性探测法处理冲突,思路清晰,算法简单,但线性探测法很容易产生堆聚现象。所谓堆聚现象,就是存入哈希表的记录在表中练成一片。按照线性探测法处理冲突,如果堆聚的记录越多,则发生冲突时的探测次数越多。

二次探测法

did_idi​ 为 12,−12,22,−22,…,q21^2,-1^2, 2^2,-2^2, \ldots, q^212,−12,22,−22,…,q2 二次序列

二次探测能有效避免“聚集”现象,但是不能够探测到哈希表上所有的存储单元,但是至少能够探测到一半。

例题:
设哈希表长为11,哈希函数为Hash (key)=key%11。存在关键码{43,7,29,22,16,92,44,8,19},采用二次探测法处理冲突,建立的hash表为( )

  • A、  
  • B、

     

  • C、 
  • D、其他几项都不对

43,7,29,22,16,92,44,8,19
43%11 = 10 H[10] = 43
7%11 = 7 H[7] = 7
29%11 = 7 H[7] = 29 f发生哈希冲突,那么向右移动一位 H[8] = 29
22%11 = 0 H[0] = 22
16%11 = 5 H[5] = 16
92%11 = 4 H[4] = 92
44%11= 0 H[0] = 44 发生了哈希冲突 ,那么向右移动一位 H[1] = 44
8 %11= 9 H[ 9] = 8
19 %11= 8 H[ 8] =19 发生哈希冲突 ,先向右边移动一位, H[ 9] =19 发生冲突,那么向左移动一位H[ 7] =19 依旧发生冲突,向右边移动两位,H[10] = 19 依旧冲突。向左移动两位,H[ 6] =19
故选择A

2.2链地址法

链地址法也成为拉链法。其基本思路是:将所有具有相同哈希地址的而不同关键字的数据元素连接到同一个单链表中。如果选定的哈希表长度为m,则可将哈希表定义为一个有m个头指针组成的指针数组T[0…m-1],凡是哈希地址为i的数据元素,均以节点的形式插入到T[i]为头指针的单链表中。并且新的元素插入到链表的前端,这不仅因为方便,还因为经常发生这样的事实:新近插入的元素最优可能不久又被访问。

链地址法特点

(1)拉链法处理冲突简单,且无堆积现象,即非同义词决不会发生冲突,因此平均查找长度较短;
(2)由于拉链法中各链表上的结点空间是动态申请的,故它更适合于造表前无法确定表长的情况;
(3)开放定址法为减少冲突,要求装填因子α较小,故当结点规模较大时会浪费很多空间。而拉链法中可取α≥1,且结点较大时,拉链法中增加的指针域可忽略不计,因此节省空间;
(4)在用拉链法构造的散列表中,删除结点的操作易于实现。只要简单地删去链表上相应的结点即可。而对开放地址法构造的散列表,删除结点不能简单地将被删结点的空间置为空,否则将截断在它之后填人散列表的同义词结点的查找路径。这是因为各种开放地址法中,空地址单元(即开放地址)都是查找失败的条件。因此在用开放地址法处理冲突的散列表上执行删除操作,只能在被删结点上做删除标记,而不能真正删除结点。
在这里插入图片描述

哈希表(散列表)、哈希表闭散列(线性探测、二次探测)解决冲突、负载因子 哈希概念 常规搜索:   数据杂乱无章——-&amp;amp;gt;顺序查找—–&amp;amp;gt;时间复杂度0(n)。   数据有序—–&amp;amp;gt;二分查找——&amp;amp;gt;时间复杂度0(log(n))。   建立二叉搜索树—–&amp;amp;gt;时间复杂度0(n)(单支树)。 理想的搜索方法是:可以不经过任何比较,一次直接从表中得到要搜索的元素,如果构造一种存储结构,通过某种函数使元素的存储位置与它的关键码之间能够建立一一映 阅读详情

相关推荐

算法之散列表:基于拉链法的高效查找实现

在编程学习的道路上,算法是解决各类复杂问题的核心工具,其重要性不言而喻。我在学习算法的过程中,收获了许多宝贵的知识,但也遇到了不少挑战。深知独自面对算法难题时的困惑,所以希望通过这篇博客,能和大家一起深入学习算法知识,在交流分享中共同进步,让更多人领略算法的魅力,提升编程技能。

wj_rdk的博客 1803

哈希表的创建

在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使每个关键字和表中唯一的存储位置相对应,称这个对应关系f为哈希(散列)函数,根据这个思想建立的表为哈希表。   若key1≠key2, 而f(key1)=f(key2), 则这种现象称为冲突,且key1和key2对哈希函数f来说是同义词。   根据设定的哈希函数f=H(key)和处理冲突的方法,将一组关键字映像到一个有限的连续的地址集上,

sanqima的专栏 3万+

《Linux运维总结:etcd 3.5.15集群数据备份与恢复》

《Linux运维总结:etcd 3.5.15集群数据备份与恢复》

东城绝神 1079

阿里面试必问:Hash冲突怎么办,哪些解决散列冲突的方法?

通过构造性能良好的哈希函数,可以减少冲突,但一般不可能完全避免冲突,因此解决冲突是哈希法的另一个关键问题。创建哈希表和查找哈希表都会遇到冲突,两种情况下解决冲突的方法应该一致。下面以创建哈希表为例,说明解决冲突的方法。这种方法也称再散列法,其基本思想是:当关键字key的哈希地址出现冲突时,以p为基础,产生另一个哈希地址p1,如果p1仍然冲突,再以p为基础,产生另一个哈希地址p2,…,直到找出一个不冲突的哈希地址pi ,将相应元素存入其中。

Java烂猪皮 904

CTransformers: 高效的Python语言模型绑定库

CTransformers是一个为C/C++实现的Transformer模型提供Python绑定的开源库。它基于GGML库构建,旨在为开发者提供一种高效且易用的方式来在Python中使用各种流行的语言模型。支持多种流行的语言模型,如GPT-2、LLaMA、Falcon等提供统一的简单API接口支持GPU加速(CUDA和Metal)与Hugging Face Transformers和LangChain集成支持流式输出和嵌入计算。

helloaiworld的博客 1267

最新测算源码PHP算命源码-风水八字-八字起名-塔罗牌占卜

未来,随着技术的发展和用户需求的变化,我们可以继续对系统进行升级和优化,以满足更多用户的需求和期望。数据库设计:创建一个名为bazi的数据库表,包含以下字段:id(自增ID)、name(姓名)、sex(性别)、birth_date(出生日期)、birth_time(出生时间)、bazi(八字结果)。数据库设计:创建一个包含塔罗牌信息的数据库表,如tarot_cards,包含字段:id(塔罗牌ID)、name(塔罗牌名称)、meaning(塔罗牌含义)等。根据操作系统的不同,PHP的安装方法会有所不同。

shanbeizi的博客 2418

数据结构期末复习-哈希表的6种构造方法和4种解决冲突方法

文章目录哈希表的概念哈希表散列法存储的基本思想优点缺点哈希方法(杂凑法)哈希函数(杂凑函数)哈希表(杂凑表)冲突哈希方法必须解决以下两个问题构造好的哈希函数制定一个好的解决冲突的方案哈希函数的构造方法直接定址法Hash(key)=a * key+b (a、b为常数)优点缺点举例除留余数法Hash(key)=key mod p (p是一个整数)特点关键技巧数字分析法特点举例平方取中法特点理由例折叠法特点适用于移位法间界叠加法举例随机数法Hash(key)=random(key) (random为随机

博客地址 www.sec0nd.top 1万+

高压脉冲发生器的各种电路图

高压脉冲发生器的各种电路图

qq_65102825的博客 5902

哈希表(几种建表和解决冲突的方法)

什么是哈希表 哈希表用的是 数组支持按照下标随机访问数据的特性 ,所以哈希表其实就是数组的一种扩展,由数组演化而来。 可以说,如果没有数组,就没有散列表。 哈希表存储的是由键(key)和值(value)组成的数据。 —-知乎 根据设定的哈希函数H(key)和处理冲突的方法将一组关键字影像到一个有限的连续的地址集(区间)上,并以关键字在地址集中的‘像’作为记录在表中的存储位置,这种表就是哈希表。这一个映像的过程就是哈希造表或散列,所得到的存储位置就是哈希地址或散列地址 哈希冲突:所谓哈希冲突,简单来说,

CrazyRabbitttt 2028

【天气雷达】双偏振产品-差分反射率ZDR详解

双偏振产品-差分反射率ZDR详解。

珞瑜的博客 5408

数据库常见面试题(附答案)

1.事务四大特性 原子性,要么执行,要么不执行 隔离性,所有操作全部执行完以前,其它会话不能看到过程 一致性,事务前后,数据总额一致 持久性,一旦事务提交,对数据的改变就是永久的 2.数据库隔离级别,每个级别会引发什么问题,mysql默认是哪个级别 脏读:事务B读取事务A还没有提交的数据 不可重复读:两次事务读的数据不一致 幻读:事务A修改了数据,事务B也修改了数据,这时在事务A看...

csdn问鼎 46万+

哈希表(散列表)C/C++代码实现

哈希表(散列表): 1,构造散列函数 最常用的方法是除留余数法: H(key) = key%p 这个方法的关键是选取适当的p, 一般情况下,可以选p为小于表长的最大质数。例如表长m=100, 可取p=97。 2,处理冲突 选择一个 “好” 的散列函数可以在一定程度上减少冲突,但在实际应用中,很难完全避免发生冲突 1,开放地址法 (1)线性勘测法 (2)二次探测法 (3)伪随机探测法 线性探测法的优点是:只要散列表未填满,总能 找到一个不发生冲突的地址。缺点是:会产生 ”二次聚集“ 现象。而二次探测法和伪随机

Ycy的博客 1万+

YOLO11实战优化:长尾分布解决 | 引入Seesaw Loss配合YOLO11分类头,完美应对类别极其不平衡的现实业务场景

摘要: YOLO11在工业缺陷检测等长尾分布场景中面临尾部类别检测失效的问题,根源在于头部类别样本的负样本梯度压制了尾部类别的学习。传统方法如重采样、Focal Loss等效果有限。Seesaw Loss通过动态调整缓解因子和补偿因子,平衡类别间的梯度分布,结合YOLO11的解耦分类头、Anchor-Free设计和C2PSA/C3K2模块,显著提升尾部类别识别能力。文章详细解析了Seesaw Loss的数学原理,并提供了可直接集成到YOLO11的PyTorch实现代码,为长尾分布下的目标检测提供了实用解决方

2601_95807009的博客 252

哈希表(散列表)详解

深入理解哈希表,哈希函数的构造和解决哈希冲突的方法

不能再留遗憾了的博客 2302

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

散列表(哈希表)知识详解

哈希表知识总结

m0_57105290的博客 6514

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

数据结构☞散列表

散列表(Hash Table) 散列表的英文叫“Hash Table”,我们平时也叫它“哈希表”或者“Hash 表”。 散列表用的是数组支持按照下标随机访问数据的特性,所以散列表其实就是数组的一种扩展,由数组演化而来。可以说,如果没有数组,就没有散列表。 key:键或者关键字。 散列函数(或“Hash 函数”“哈希函数”):把key值转化为数组下标的映射方法。 散列函数计算得到的值就叫作散列值(或“Hash 值”“哈希值”)。 散列函数 散列函数设计的基本要求: 散列函数计算得到的散列值是一个非负整

weixin_47251999的博客 2万+

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

哈希表(散列表)查找的详解

前言博客编写人:Willam 博客编写时间:2017/3/29 博主邮箱:2930526477@qq.com(有志同道合之人,可以加qq交流交流编程心得)1、哈希表查找介绍我之前介绍两种方向的查找算法: 静态查找算法(折半查找、插值查找、斐波那契查找、分块查找) 动态查找算法(二叉排序树、平衡二叉树、B-树、B+树) 但是,这些查找算法都是通过从表头开始,挨个挨个的比较记录,才得到我们需要查找的关键

William 8310

一篇就能学懂的散列表,让哈希表数据结构大放光彩

一篇就能学懂的散列表,让哈希表数据结构大放光彩

Williamtym的博客 3228

【算法】哈希表

本次为大家带来的是哈希表在算法中的应用与实践,主要讲解哈希表的思路以及在算法题中的应用,本篇文章由于是面向算法党的,对于工程实现部分讲解较为粗糙,以后会在STL中详细讲解工程实现。当然,本篇文章会给出哈希表的两种快速实现,希望大家能将这两个模板理解记忆,方便面试中或者算法竞赛中快速实现。散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。

白晨的博客 3347

散列表(哈希表)及其存储结构和特点详解

顺序存储的结构类型需要一个一个地按顺序访问元素,当这个总量很大且我们所要访问的元素比较靠后时,性能就会很低。散列表是一种空间换时间的存储结构,是在算法中提升效率的一种比较常用的方式,但是所需空间太大也会让人头疼,所以通常需要在二者之间权衡。我们会在之后的具体算法章节中得到更多的领悟。 什么是散列表 让我们想一下,若在手机通信录中查找一个人,那我们应该不会从第 1 个人一直找下去,因为这样实在是...

空杯 8444

哈希表(散列表)原理详解

哈希表(散列表)原理详解

那年聪聪 30万+

哈希表、散列表

1.基本介绍 可能你听过散列表,散列函数,它们跟哈希表,哈希函数是一个概念。接下来以"哈希"来作梳理。 在介绍哈希表的时候,先来比较一下数组和链表的优缺点: 数组:寻址容易,但插入和删除元素比较麻烦; 链表:插入和删除元素容易,但寻址比较麻烦。 那么有没有一种数据结构是既能结合这两种的优点同时也能避免这两种数据结构所带来的缺点呢? 哈希表就是这样的数据结构: 哈希表的底层实际上是基于数组来存储的,当插入键值对时,并不是直接插入该数组中,而是通过对键进行Hash运算得到Hash值,然后和数组容量取模,得到

Deronn的博客 6235

哈希表(散列表)基础知识总结

目录 1.散列表概述 1.1散列表查找定义 1.2散列表查找步骤 2.散列函数的构造方法 2.1直接定址法 2.2数字分析法 2.3平方取中法 2.4折叠法 2.5除留余数法 2.6随机数法 3.处理散列冲突的方法 3.1开放定址法 3.2再散列函数法 3.3链地址法 3.4公共溢出区法 4.散列表查找实现 4.1散列表查找算法实现 4.2散列表查找性能分析 ...

qq_40692109的博客 2543

数据结构与算法分析:哈希表

哈希表又叫散列表,是实现字典操作的一种有效数据结构。哈希表的查询效率极高,在没有冲突(后面会介绍)的情况下可做到一次存取便能得到所查记录,在理想情况下,查找一个元素的平均时间为O(1)(最差情况下散列表中查找一个元素的时间与链表中查找的时间相同:O(n),但实际情况中一般散列表的性能是比较好的)。

liyuefeilong的专栏 9006

算法设计与分析——散列表/哈希表(Hash Table)(三):散列表原理

直接寻址技术的缺点是非常明显的:如果全域U很大,则在一台标准的计算机可用内存容量中,要存储大小为∣U∣|U|∣U∣的一张表TTT也许不太实际,甚至是不可能的。还有,实际存储的关键字集合KKK相对UUU来说可能很小,使得分配给TTT的大部分空间都将浪费掉。 当存储在字典中的关键字集合KKK比所有可能的关键字的全域UUU要小许多时,散列表需要的存储空间要比直接寻址表少得多。特别地,我们能将散列表的存储需求降至Θ(∣K∣)\Theta(|K|)Θ(∣K∣),同时散列表中查找一个元素的优势仍得到保持,只需要O(1)

冯·诺依曼 1万+
上一篇: 刷题番外--赛码网之C++读取
下一篇: 深度探索array与forward_list
null_one
博客等级 码龄8年 847粉丝 87原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值