问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

数据结构详解:散列表的概念、构造与冲突处理

创作时间:
作者:
@小白创作中心

数据结构详解:散列表的概念、构造与冲突处理

引用
CSDN
1.
https://blog.csdn.net/a_rain2333/article/details/137936512

散列表(哈希表)是一种高效的数据结构,它通过散列函数将关键字映射到存储地址,从而实现快速的查找、插入和删除操作。本文将详细介绍散列表的基本概念、散列函数的构造方法以及处理冲突的两种主要方法:拉链法和开放定址法。

7.5.1 散列表的基本概念

散列表(哈希表,Hash Table)是一种数据结构。其特点是:可以根据数据元素的关键字计算出它在散列表中的存储地址。

  • 散列函数(哈希函数):Addr=H(key)建立了“关键字”→“存储地址”的映射关系
  • 冲突(碰撞):在散列表中插入一个数据元素时,需要根据关键字的值确定其存储地址,若该地址已经存储了其他元素,则称这种情况为“冲突(碰撞)”
  • 同义词:若不同的关键字通过散列函数映射到同一个存储地址,则称它们为“同义词”

如何减少“冲突”?

对于散列函数 H(key)=key%13 来说,1 和 14 是“同义词”,可以构造更适合的散列函数,让各个关键字尽可能地映射到不同的存储位置,从而减少“冲突”

Eg:把散列函数改为H(key)=key%12,则不发生冲突

  • 19%12=7
  • 14%12=2
  • 23%12=11
  • 1%12=1

如何处理冲突?

  • 拉链法(又称链接法、链地址法):把所有“同义词”存储在一个链表中。
  • 开放定址法:如果发生“冲突”,就给新元素找另一个空闲位置。

7.5.2 散列函数的构造

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

设计散列函数时应该注意:

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

散列表表长为m,取一个不大于m但最接近或等于m的质数p

注:质数又称素数。指除了1和此整数自身外,不能被其他自然数整除的数

适用场景:较为通用,只要关键字是整数即可

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

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

适用场景:关键字分布基本连续

数字分析法——选取数码分布较为均匀的若干位作为散列地址

设关键字是r进制数(如十进制数),而r个数码在各位上出现的频率不一定相同,可能在某些位上分布均匀一些,每种数码出现的机会均等;而在某些位上分布不均匀,只有某几种数码经常出现,此时可选取数码分布较为均匀的若干位作为散列地址。

适用场景:关键字集合已知,且关键字的某几个数码位分布均匀。

平方取中法——取关键字的平方值的中间几位作为散列地址。

具体取多少位要视实际情况而定。这种方法得到的散列地址与关键字的每位都有关系,因此使得散列地址分布比较均匀。

适用场景:关键字的每位取值都不够均匀。

7.5.3_1 处理冲突的方法_拉链法

拉链法(又称链接法、链地址法):把所有“同义词”存储在一个链表中

如何在散列表(拉链法解决冲突)中插入一个新元素?

Step 1:结合散列函数计算新元素的散列地址

Step 2:将新元素插入散列地址对应的链表(可用头插法,也可用尾插法)

散列表的插⼊操作(拉链法解决冲突)

散列表的查找操作(拉链法解决冲突)

查找目标20,计算目标元素存储地址:20%13=7; 20查找成功,查找长度=1

查找目标66,计算目标元素存储地址:66%13=1; 66查找失败,查找长度=4

查找目标21,计算目标元素存储地址:21%13=8; 21查找失败,查找长度=0

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

注:有的教材会把“空指针的对比”也计入查找长度。但考试中默认只统计 “关键字对比次数”

散列表的删除操作(拉链法解决冲突)

删除目标:27 ,计算目标元素存储地址:27%13=1; 27查找成功,删除成功

删除目标:20 ,计算目标元素存储地址:20%13=7; 20查找成功,删除成功

删除目标:66 ,计算目标元素存储地址:66%13=1; 66查找失败,删除失败

7.5.3_2 处理冲突的方法_开放定址法

开放定址法的基本原理

开放定址法:如果发生“冲突”,就给新元素找另一个空闲位置。

注:d表示第i次发生冲突时,下一个探测地址与初始散列地址的相对偏移量。

根据散列函数H(key),求得初始散列地址。若发生冲突,如何找到“另一个空闲位置”?

如何删除一个元素:

Step 1:先根据散列函数算出散列地址,并对比关键字是否匹配。若匹配,则“查找成功”

Step 2:若关键字不匹配,则根据“探测序列”对比下一个地址的关键字,直到“查找成功”或“查找失败”

Step 3:若“查找成功”,则删除找到的元素

特别注意:关于删除操作

例:长度为13的散列表状态如下图所示,散列函数H(key)=key%13,采用线性探测法解决冲突。

正确示范:查找元素1

计算元素1的初始散列地址=1%13=1。对比位置#1,关键字不等于1;

根据线性探测法的探测序列,继续对比位置#2,关键字不等于1;

根据线性探测法的探测序列,继续对比位置#3,该位置原关键字已删,继续探测后一个位置;

根据线性探测法的探测序列,继续对比位置#4,关键字等于1,查找成功。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号