散链表基本操作讲解

散列表(哈希表,Hash Table):是⼀种数据结构。特点是:可以根据数据元素的关键字

计算出它在散列表中的存储地址

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

简单来说就是一个数组加上映射关系

但是散链表会出现冲突以及同义词解析来讲解一下这两个词语

冲突(碰撞):在散列表中插⼊⼀个数据元素时,需要根据关键字的值确定其存储地址,若

该地址已经存储了其他元素,则称这种情况为"冲突(碰撞)"

同义词:若不同的关键字通过散列函数映射到同⼀个存储地址,则称它们为"同义词"

如何减少冲突呢?最有效的途径就是构造一个好的函数(散列函数)

一般是采取数组长度的质数

质数:只能被1和本身整除的数

和数,除了一和本身还能被其他整数整除

若"冲突"⽆可避免,如何处理冲突?

拉链法(⼜称链接法、链地址法):把所有"同义词"存储在⼀个链表中即数组中存储的是一个链表的指针

开放定址法;

开放定址法:如果发⽣"冲突",就给新元素找另⼀个空闲位置。

注意这里待解决的问题,解析来我们探讨待解决的问题。

插播一下哈希函数的构造

哈希函数的构造

设计函数时应该尽量避免函数带来的地址冲突,主要有四种办法。

除留余数法

直接定址法

数字分析法

平方取中法

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

  1. 定义域必须涵盖所有可能出现的关键字。
  2. 值域不能超出散列表的地址范围。
  3. 尽可能减少冲突。散列函数计算出来的地
    址应尽可能均匀分布在整个地址空间。
  4. 散列函数应尽量简单,能够快速计算出任
    意⼀个关键字对应的散列地址。**

简单概括就是,包含所有关键字同时映射后不能超出给定的数组范围同时还要减少冲突且简单。

除留余数法

散列表表⻓为m,取⼀个不⼤于m但最接近或等于m的质数p

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

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

直接定址法

我记为a*X+b法

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

其中,a和b是常数。这种⽅法计算最简单,且不会产⽣冲突。若关键字分布不连续,空位较多,

则会造成存储空间的浪费。

适⽤场景:关键字分布基本连续。例如学号的存储

数字分析法

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

适合于杂乱的数据

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

平方取中法

平⽅取中法------取关键字的平⽅值的中间⼏位作为散列地址

这种⽅法得到的散列地址与关键字的每位都有关系,因此使得
散列地址分布⽐较均匀。

主要记住除留余数法和ax+b法

接下来介绍处理冲突的方法

处理冲突

拉链法

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

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

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

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

主要要学会计算查找长度

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

注:有的教材会把"空指针的对⽐"也计⼊查找⻓度。但考试中默认只统计"关键字对⽐次数"。

接下来看删除操作

删除就是普通的链表删除操作

拓展:插⼊操作的⼩优化

新元素⽤"头插法"插⼊链表,每个链表是乱序的

新元素插⼊链表时,若能保持链表有序,可以略微提⾼"查找"效率。

处理冲突的办法

处理地址冲突的办法同样也有四种如上图所示

线性探测法

平方探测法

双散列法

伪随机序列法

接下来挨个介绍

开放地址法

开放定址法:如果发⽣"冲突",就给新元素找另⼀个空闲位置。

用一下规则找新地址

需要设定一个探测序列

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

根具探测序列的不同区分四种方法

首先介绍线性探测地址法

线性探测法,di = 0, 1, 2, 3, ..., m-1

初始散列地址H0=1%13=1,发⽣冲突(第1次)

H1 = (1 + 1) % 13 = 2,发⽣冲突(第2次)

H2 = (1 + 2) % 13 = 3,发⽣冲突(第3次)

H3 = (1 + 3) % 13 = 4,未发⽣冲突,插⼊位置#4

线性探测法可以探测到列表的每一个地址

接下来看平方探测法

平方探测法

前面说过不一样的就是探测序列不一样而已

双散列法

其实就是重新定义了一个哈希函数

伪随机序列

针对于伪随机序列来说就是序列是人自己随便定义的

接下来我们看四种操作的删除操作

如何删除⼀个元素:

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

Step 2:若关键字不匹配,则根据"探测序列"对⽐下⼀个地址的关键字,直到"查找成功"或"查

找失败"

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

线性探测法的删除操作

针对于3号位值空导致线性查找失败的情况下我们可以在空的位置加一个tag位每次进行删除操作时置tag为为1表示删除过该元素。这样下次删除探测的时候就可以避免空位置导致删除失败的情况了。

注意红色框中的位置。

由于只是逻辑删除,但是标已删除位置也还会导致地址浪费的情况此时就需要定时整理列表

接下里探讨一下覆盖率的问题

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

只要散列表中有空闲位置,就⼀定可以插⼊成功

记住一下4j+3这里是数论的知识不予讨论记住就好

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

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

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

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

相关推荐
chao_7895 小时前
二分查找篇——搜索旋转排序数组【LeetCode】两次二分查找
开发语言·数据结构·python·算法·leetcode
秋说7 小时前
【PTA数据结构 | C语言版】一元多项式求导
c语言·数据结构·算法
Maybyy8 小时前
力扣61.旋转链表
算法·leetcode·链表
谭林杰8 小时前
B树和B+树
数据结构·b树
卡卡卡卡罗特10 小时前
每日mysql
数据结构·算法
chao_78910 小时前
二分查找篇——搜索旋转排序数组【LeetCode】一次二分查找
数据结构·python·算法·leetcode·二分查找
lifallen11 小时前
Paimon 原子提交实现
java·大数据·数据结构·数据库·后端·算法
丶小鱼丶11 小时前
链表算法之【合并两个有序链表】
java·算法·链表
不吃洋葱.11 小时前
前缀和|差分
数据结构·算法
哦吼!13 小时前
数据结构—二叉树(二)
数据结构