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

news2024/11/17 11:33:17

目录

1.散列表的基本概念

2.散列表的查找

3.散列函数的构造方法

1.直接定址法

2.除留余数法

4.散列表解决冲突的方法

1.开放定址法

2.链地址法

1.散列表的基本概念

基本思想:记录的存储位置与关键字之间存在的对应关系

对应关系——hash函数

Loc(i) = H(keyi)

Hash:哈希——翻译为:散列、杂凑(感觉还是哈希听起来更好听)

是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

能使对一个数据序列的访问过程更加迅速有效,通过散列函数,数据元素将被更快地定位。

例题1

若将学生信息按如下方武存入计算机,如 将2001011810211的所有信息存入V[11]单元: 将2001011810207的所有信息存入V[07]单元: …… 将2001011810231的所有信息存入V[31]单元。

通过取出最后两位定义一个关键存储。

例题2

数据元素序列(21,23,39,9,25,11),若规定每个元素k的存储地址H(k)=k,请画出存储结构图。

  

按照每一个元素的值,存储到相应下标的位置上,从而完成对散列表的构建。

散列表的若干术语

散列方法(杂凑法)

  1. 选取某个函数,依该函数按关键字计算元素的存储位置,并按此存放;

  2. 查找时,由同一个函数对给定值k计算地址,将k与地址单元中元素关键码进行比,确定查找是否成功。

散列函数(杂凑函数):散列方法中使用的转换函数

散列表(杂凑表):按上述思想构造的表(也就是例题2所建构出来的图表)

散列函数:H(key)=k

冲突:不同的关键码映射到同一个散列地址,key1≠key2,但是H(key1)=H(key2)

例题:有6个元素的关键码分别为:(25,21,39,9,23,11)。

  1. 选取关键码与元素位置间的函数为H(k)= k mod 7,

  2. 地址编号从0-6。

  3. 这时候会发现有好多计算出来的关键词一致,造成了冲突

2.散列表的查找

 

 根据散列函数H(key) = k

查找key=9,则访问H(9)=9号地址,若内容为9则成功;

若查不到,则返回一个特殊值,如空指针或空记录。

优点:查找效率高

缺点:空间效率低!

 

 注意:第一次计算的时候,即使不符合,也不能说明Hash表里面没有该值。

例题

已知一组关键字(19, 14, 23, 1, 68, 20, 84, 27, 55, 11, 10, 79)

散列函数为:H(key)=key mod13,散列表长为m=16,

设每个记录的查找概率相等

线性探测再散列

线性探测再散列处理冲突,即Hi=(H(key)+di) MOD m

 

 H(19)=6 H(84)=6冲突,H(84)=(6+1)MOD13=7

H(14)=1 冲突,H(84)=(6+2)MOD13=8

H(23)=10 H(27)=1冲突,H(27)=(1+1)MOD13=2

H(1)=1 冲突,H(1)=(1+1)MOD13=2 冲突,H(27)=(1+2)MOD13=3

H(68)=3 冲突,H(27)=(1+3)MOD13=4

H(20)=7 ……

ASL=(1 * 6 + 2 + 3 * 3 + 4 + 9)/12=2.5

用链地址法处理冲突

 

 散列表的查找效率分析

使用平均查找长度ASL来衡量查找算法,ASL取决于

  1. 散列函数

  2. 处理冲突的方法

  3. 散列表的装填因子α

α=表中填入的记录数/哈希表长度

ASL与装填因子α有关!既不是严格的O(1),也不是O(n)

 

 结论

  1. 散列表技术具有很好的平均性能,优于一些传统的技术

  2. 链地址法优于开地址法

  3. 除留余数法作散列函数优于其它类型函数

3.散列函数的构造方法

 

散列存储

选取某个函数,依该函数按关键字计算元素的存储位置

Loc(i)=H(keyi)

冲突,不同的关键码映射到同一个散列地址

key1≠key2,但是H(key1)=H(key2)

在散列查找方法中,冲突是不可能避免的,只能尽可能减少。

使用散列表要解决两个重要的问题

1)构造好的散列函数

  1. 所选函数尽可能简单,以便提高转换速度

  2. 所选函数对关键码计算出的地址,应该在散列地址集中致均匀分布,以减少空间浪费

2)制定一个好的解决冲突的方案

查找时,如果从散列函数计算出的地址中查不到关键码,则应该依据解决冲突的规则,有规律地查询其它相关单元。

构造散列函数考虑的因素

  1. 执行速度(即计算散列函数所需要的时间)

  2. 关键字的长度

  3. 散列表的大小

  4. 关键字的分布情况

  5. 查找频率

所以根据元素集合的特性构造,我们就必须考虑到散列查找实际上就是以空间换时间,但我们仍然希望散列的地址空间尽量小而且无论是用什么方法进行存储,目的都是尽可能均匀地存放元素,以避免冲突。

通常,我们会采取以下六种常见方法:

  1. 直接定址法

  2. 数字分析法

  3. 平方取中法

  4. 折叠法

  5. 除留余数法

  6. 随机数法

接下来,主要来介绍上述的6种方法

1.直接定址法

Hash(key)=a·key+b(a、b为常数)

优点:以关键码key的某个线性函数值为散列地址,不会产生冲突。

例:{100, 300, 500, 700, 800, 900} 散列函数Hash(key) = key/100 (a=1/100, b = 0)

 

2.除留余数法

Hash(key) = key mod p(p是一个整数)

关键在于选取合适的p

技巧在于设表长为m,取p≤m且为质数

例:{15, 23, 27, 38, 53, 61, 70},

散列函数Hash(key)=key mod 7

 

4.散列表解决冲突的方法

  1. 开放定址法(开地址法)

  2. 链地址法(拉链法)

  3. 再散列表法(双散链函数法)

  4. 建立一个公共的溢出区

1.开放定址法

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

例如:除留余数法 Hi = (Hash(key) + di) mod m di为增量序列

常用方法

  1. 线性探测法 di为1,2,……m-1线性序列

  2. 二次探测法 di为1^2, -1^2,…… q^2二次序列

  3. 伪随机探测法 di为伪随机数序列

线性探测法

Hi = (Hash(key) + di) mod m (1≤ i ≤ m)

其中的m为散列表长度,di为增量序列1,2,……m-1,且di = i

一旦冲突,就找到下一个地址,直到找到空地址存入。

例:关键码集为{47, 7, 29, 11, 16, 92, 22, 8, 3},散列表的表长为m=11;散列函数为Hash(key) = key mod 11;拟用线性探测是否有冲突。建散列表加下:

  

如图,因为当29mod11得到7,与我们的原有的7相冲突,此时,通过线性探测法,我们应该判断7的下一个位置,是否为空,若为空则线性往下进行存储。

  

依次往复地进行计算、存储,有如下图形式:

  

当我们要对其中数据进行查找的时候,实际上也是要重复上述的操作的,也就是取模,如果发现数据不符,则继续往后面线性查找。

二次探测法

例:关键码集为{47, 7, 29, 11, 16, 92, 22, 8, 3},散列表的表长为m=11;散列函数为Hash(key) = key mod 11;拟用二次探测法是否有冲突。

Hi = (Hash(key) + di) mod m (1≤ i ≤ m)

其中的m为散列表长度,di为增量序列1,2,……m-1,且di = i

其中:m为散列表长度,m要求是某个4k+3的质数;

di为增量序列1^2 , -1^2, 2^2, -2^2,……, q^2

  

例如存储3的时候发现原来的位置已经被占用了,即Hash(3)=3,散列地址冲突,由 H1=(Hash(3)+12)mod11=4,仍然冲突,则继续H2=(Hash(3)-12)mod 11 = 2,找到空的散列地址,存入。

伪随机探测法

H1 = (Hash(key)+di) mod m (1≤ i ≤ m)

其中:m为散列表长度,di为伪随机数

2.链地址法

基本思想:相同散列地址的记录链成一单链表

m个散列地址就设m个单链表,然后用一个数组将m个单链表的表头指针存储起来,形成一个动态的结构。

例如:一组关键字为{19, 14, 23, 1, 68, 20, 84, 27, 55, 11, 10, 79},散列函数为Hash(key)=key mod 13

 

链地址法建立散列表步骤

Step1:取数据元素的关键字key,计算其散列函数值(地址)。若该地址对应的链表为空,则将该元素插入此链表;否则执行Step2解决冲突。

Step2:根据选择的冲突处理方法,计算关键字key的下一个存储地址。若该地址对应的链表为不为空,则利用链表的前插法或后插法将该元素插入此链表。

链地址法的优点

  1. 非同义词不会产生冲突,无“集聚”现象

  2. 链表上结点空间动态申请,更适合子表不确定的情况

 

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

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

相关文章

关于外包被开要怎么维护自己的权益

我一直以为外包被开都是没有任何赔偿的,之前网上对于外包的消息都是说,没有任何赔偿或者是怕麻烦然后就干脆放弃了的各种评论。。。但是最近我在问到一个朋友的时候,他很好的维护了自己的权益。最后获得了N1 保留证据 当被告知外包需要你离场…

牛客网语法篇刷题(C语言) — 运算

作者主页:paper jie的博客_CSDN博客-C语言,算法详解领域博主 本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。 本文录入于《C语言-语法篇》专栏,本专栏是针对于大学生,编程小白…

单链表OJ题:LeetCode--138.复制带随即指针的链表

朋友们、伙计们,我们又见面了,本期来给大家解读一下LeetCode中第138道单链表OJ题,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成! 数据结构与算法专栏:数据结构与算法 个 人…

python使用Faker库进行生成模拟mock数据(基本使用+五个小案例)

使用faker进行生成模拟(mock))数据 文章目录 使用faker进行生成模拟(mock))数据一、Faker库安装二、Faker库基本介绍三、案例1:Faker库生成核酸数据四、案例2:生成不重复的人名和地名五、案例3:生成有时间期限的低保数据六、案例4&#xff1a…

01-Vue 项目环境搭建和创建准备工作

一. 学习目标 掌握 Vue 项目创建的依赖环境掌握 Vue 项目创建过程 二. 学习内容 掌握搭建 Vue 项目准备环境掌握 Vue 项目创建过程了解 Vue 项目各子目录 三. 学习过程 1. 准备工作 (1)安装Node.js 打开node.js官网:Node.js &#xff0…

【状态估计】无迹卡尔曼滤波(UKF)应用于FitzHugh-Nagumo神经元动力学研究(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

详解ASP.NET Core 在 IIS 下的两种部署模式

KestrelServer最大的优势体现在它的跨平台的能力,如果ASP.NET CORE应用只需要部署在Windows环境下,IIS也是不错的选择。ASP.NET CORE应用针对IIS具有两种部署模式,它们都依赖于一个IIS针对ASP.NET CORE Core的扩展模块。 一、ASP.NET CORE C…

UML类图入门

UML类图入门 UML是一个通用的可视化建模描述语言,通过图形符号和文字来对系统进行建模。适用于各种软件的开发方法、生命周期的各个阶段。 类的UML图示 类使用包含类型、属性和操作(方法)且带有分割线的长方形来表示,如&#x…

人际关系的学习改进

表达的目的:让别人对你感兴趣 不要有苦劳而无功劳 爱的五种语言:表达爱的语言 人类存在的中心,是渴望和人亲近,被人所爱。婚姻即是被设计满足这种亲密关系和爱的需求的;把注意力集中在情绪健康所需的那片爱土上&…

【C++ 程序设计】第 4 章:运算符重载

目录 一、运算符重载的概念 (1)重载运算符的概念 ① 重载运算符的概念 ② 可重载的运算符 ③ 不可重载的运算符 ④ 运算符的优先级 (2)重载运算符为类的成员函数 (3)重载运算符为友元函数 &#…

【Linux】Docker部署镜像环境 (持续更新ing)

防火墙 1、查看防火墙状态 sudo systemctl status ufw 2、开启防火墙 sudo systemctl start ufw 3、关闭防火墙 sudo systemctl stop ufw 4、开机禁止开启防火墙 sudo systemctl disabled ufw 5、开启自启防火墙 sudo systemctl enabled ufw Elasticsearch 1、安装指定版本 比…

使用Pillow库轻松实现图像尺寸调整——>使每个图像具有相同的大小,方便模型处理和训练

在计算机视觉领域,对图像进行尺寸调整是一项非常常见的操作。在训练深度神经网络时,因为计算资源和内存限制的原因,我们通常需要将图像缩放到相同的尺寸。 在本文中,我们将介绍如何使用Python中的Pillow库对图像进行尺寸调整,并提供一个示例程序resize_images。 1. Pytho…

VulnHub靶场-Chronos

目录 0x01 声明: 0x02 简介: 0x03 环境准备: 0x04 信息收集: 1、主机发现 2、NMAP扫描 3、访问业务 4、目录探测 5、查看网页代码 0x05 渗透测试过程: 1、Burp Suite抓包 2、构造payload 测试是否可以外联…

CSS基础学习--5 background背景

一、介绍&#xff1a; CSS 背景属性用于定义HTML元素的背景。 CSS 属性定义背景效果: background-color 背景颜色background-image 背景图片background-repeatbackground-attachmentbackground-position 二、属性 2.1、background-color 属性定义了元素的背景颜色 <s…

根据word模板生成pdf文件

1、首先建一个word&#xff0c;插入一个表格&#xff0c;需要填充的值用${parame}代替 &#xff08;注意&#xff1a;这里的参数要和java实体类里面的参数对应起来&#xff0c;代码放在下面&#xff09; 2、制作完成后另存为xml格式 3、然后用文本编辑工具打开这个xml文件&…

CSS基础学习--6 CSS Text(文本)

一、文本颜色 color:red; 颜色属性被用来设置文字的颜色。 颜色是通过CSS最经常的指定&#xff1a; 十六进制值 - 如: &#xff03;FF0000一个RGB值 - 如: RGB(255,0,0)颜色的名称 - 如: red body {color:red;} h1 {color:#00ff00;} h2 {color:rgb(255,0,0);} 二、文本的…

【备战秋招】每日一题:4月18日美团春招:题面+题目思路 + C++/python/js/Go/java带注释

2023大厂笔试模拟练习网站&#xff08;含题解&#xff09; www.codefun2000.com 最近我们一直在将收集到的各种大厂笔试的解题思路还原成题目并制作数据&#xff0c;挂载到我们的OJ上&#xff0c;供大家学习交流&#xff0c;体会笔试难度。现已录入200道互联网大厂模拟练习题&a…

8 channel、反射、网络编程【Go语言教程】

8 channel、反射、网络编程【Go语言教程】 1 channel 1.1 概念及快速入门 channel:管道&#xff0c;主要用于不同goroutine之间的通讯 需求&#xff1a;现在要计算 1-200 的各个数的阶乘&#xff0c;并且把各个数的阶乘放入到 map 中。最后显示出来。要求使用 goroutine 完成…

[LeetCode周赛复盘] 第 349 场周赛20230611

[LeetCode周赛复盘] 第 349 场周赛20230611 一、本周周赛总结6470. 既不是最小值也不是最大值1. 题目描述2. 思路分析3. 代码实现 6465. 执行子串操作后的字典序最小字符串1. 题目描述2. 思路分析3. 代码实现 6449. 收集巧克力1. 题目描述2. 思路分析3. 代码实现 6473. 最大和…

测试老鸟总结,接口自动化测试用例设计编写,高级测试之路...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 接口信息来源 与…