深入理解开放寻址法中的三种探测序列

一、引言

开放寻址法是解决散列表中冲突的一种重要方法,当发生冲突(即两个不同的键通过散列函数计算得到相同的散列值)时,它会在散列表中寻找下一个可用的存储位置。而探测序列就是用于确定在发生冲突后,依次尝试哪些存储位置的规则。下面详细介绍线性探测、二次探测和双重散列这三种常见的探测序列。
在这里插入图片描述

二、线性探测(Linear Probing)

1. 原理

线性探测是最简单的开放寻址法探测序列。当插入一个键值对,计算出的散列值对应的存储位置已被占用时,它会按照顺序依次检查下一个存储位置(通常是逐个向后检查),直到找到一个空的存储位置为止。如果检查到散列表的末尾还没有找到空位置,就会从散列表的开头继续检查。其探测函数的公式为:
h ( k , i ) = ( h ′ ( k ) + i ) m o d m h(k, i) = (h'(k)+i) \bmod m h(k,i)=(h(k)+i)modm
其中, h ( k , i ) h(k, i) h(k,i) 是经过 i i i 次探测后得到的存储位置, h ′ ( k ) h'(k) h(k) 是初始的散列值(即通过散列函数直接计算得到的位置), i i i 是探测次数( i = 0 , 1 , 2 , ⋯ i = 0, 1, 2, \cdots i=0,1,2,), m m m 是散列表的大小。

2. 示例

假设散列表的大小 m = 10 m = 10 m=10,散列函数 h ′ ( k ) = k m o d 10 h'(k)=k \bmod 10 h(k)=kmod10。现在要依次插入键 23 23 23 33 33 33 43 43 43

  • 插入键 23 23 23 h ′ ( 23 ) = 23 m o d 10 = 3 h'(23)=23 \bmod 10 = 3 h(23)=23mod10=3,位置 3 3 3 为空,直接插入。
  • 插入键 33 33 33 h ′ ( 33 ) = 33 m o d 10 = 3 h'(33)=33 \bmod 10 = 3 h(33)=33mod10=3,位置 3 3 3 已被占用,进行第一次探测 i = 1 i = 1 i=1 h ( 33 , 1 ) = ( 3 + 1 ) m o d 10 = 4 h(33, 1)=(3 + 1)\bmod 10 = 4 h(33,1)=(3+1)mod10=4,位置 4 4 4 为空,插入到位置 4 4 4
  • 插入键 43 43 43 h ′ ( 43 ) = 43 m o d 10 = 3 h'(43)=43 \bmod 10 = 3 h(43)=43mod10=3,位置 3 3 3 已被占用,进行第一次探测 i = 1 i = 1 i=1 h ( 43 , 1 ) = ( 3 + 1 ) m o d 10 = 4 h(43, 1)=(3 + 1)\bmod 10 = 4 h(43,1)=(3+1)mod10=4,位置 4 4 4 也被占用,进行第二次探测 i = 2 i = 2 i=2 h ( 43 , 2 ) = ( 3 + 2 ) m o d 10 = 5 h(43, 2)=(3 + 2)\bmod 10 = 5 h(43,2)=(3+2)mod10=5,位置 5 5 5 为空,插入到位置 5 5 5
3. 优缺点
  • 优点:实现简单,只需要进行简单的加法和取模运算。
  • 缺点:容易产生“聚集”现象,即连续被占用的存储位置会越来越长,导致后续插入和查找操作的效率降低。

三、二次探测(Quadratic Probing)

1. 原理

二次探测通过二次函数来确定探测序列,它在发生冲突时,不是像线性探测那样逐个向后检查,而是按照二次方的步长来检查存储位置。其探测函数的公式为:
h ( k , i ) = ( h ′ ( k ) + c 1 i + c 2 i 2 ) m o d m h(k, i)=(h'(k)+c_1i + c_2i^2) \bmod m h(k,i)=(h(k)+c1i+c2i2)modm
其中, c 1 c_1 c1 c 2 c_2 c2 是正的常数, h ′ ( k ) h'(k) h(k) 是初始散列值, i i i 是探测次数( i = 0 , 1 , 2 , ⋯ i = 0, 1, 2, \cdots i=0,1,2,), m m m 是散列表的大小。常见的情况是 c 1 = c 2 = 1 c_1 = c_2 = 1 c1=c2=1

2. 示例

同样假设散列表的大小 m = 10 m = 10 m=10,散列函数 h ′ ( k ) = k m o d 10 h'(k)=k \bmod 10 h(k)=kmod10 c 1 = c 2 = 1 c_1 = c_2 = 1 c1=c2=1。要插入键 23 23 23 33 33 33 43 43 43

  • 插入键 23 23 23 h ′ ( 23 ) = 23 m o d 10 = 3 h'(23)=23 \bmod 10 = 3 h(23)=23mod10=3,位置 3 3 3 为空,直接插入。
  • 插入键 33 33 33 h ′ ( 33 ) = 33 m o d 10 = 3 h'(33)=33 \bmod 10 = 3 h(33)=33mod10=3,位置 3 3 3 已被占用,进行第一次探测 i = 1 i = 1 i=1 h ( 33 , 1 ) = ( 3 + 1 × 1 + 1 × 1 2 ) m o d 10 = 5 h(33, 1)=(3+1\times1 + 1\times1^2)\bmod 10 = 5 h(33,1)=(3+1×1+1×12)mod10=5,位置 5 5 5 为空,插入到位置 5 5 5
  • 插入键 43 43 43 h ′ ( 43 ) = 43 m o d 10 = 3 h'(43)=43 \bmod 10 = 3 h(43)=43mod10=3,位置 3 3 3 已被占用,进行第一次探测 i = 1 i = 1 i=1 h ( 43 , 1 ) = ( 3 + 1 × 1 + 1 × 1 2 ) m o d 10 = 5 h(43, 1)=(3+1\times1 + 1\times1^2)\bmod 10 = 5 h(43,1)=(3+1×1+1×12)mod10=5,位置 5 5 5 也被占用,进行第二次探测 i = 2 i = 2 i=2 h ( 43 , 2 ) = ( 3 + 1 × 2 + 1 × 2 2 ) m o d 10 = 9 h(43, 2)=(3+1\times2 + 1\times2^2)\bmod 10 = 9 h(43,2)=(3+1×2+1×22)mod10=9,位置 9 9 9 为空,插入到位置 9 9 9
3. 优缺点
  • 优点:一定程度上缓解了线性探测的“聚集”问题,因为它的探测步长是变化的。
  • 缺点:仍然可能出现二次聚集的情况,即不同的初始散列值可能会产生相同的探测序列。

四、双重散列(Double Hashing)

1. 原理

双重散列使用两个散列函数来确定探测序列。当发生冲突时,它会根据第二个散列函数计算出的步长来依次检查存储位置。其探测函数的公式为:
h ( k , i ) = ( h 1 ( k ) + i × h 2 ( k ) ) m o d m h(k, i)=(h_1(k)+i\times h_2(k)) \bmod m h(k,i)=(h1(k)+i×h2(k))modm
其中, h 1 ( k ) h_1(k) h1(k) 是第一个散列函数计算得到的初始散列值, h 2 ( k ) h_2(k) h2(k) 是第二个散列函数, i i i 是探测次数( i = 0 , 1 , 2 , ⋯ i = 0, 1, 2, \cdots i=0,1,2,), m m m 是散列表的大小。为了保证能够遍历散列表中的所有位置, h 2 ( k ) h_2(k) h2(k) 的值必须与 m m m 互质。

2. 示例

假设散列表的大小 m = 10 m = 10 m=10,第一个散列函数 h 1 ( k ) = k m o d 10 h_1(k)=k \bmod 10 h1(k)=kmod10,第二个散列函数 h 2 ( k ) = 7 − ( k m o d 7 ) h_2(k)=7-(k \bmod 7) h2(k)=7(kmod7)。要插入键 23 23 23 33 33 33 43 43 43

  • 插入键 23 23 23 h 1 ( 23 ) = 23 m o d 10 = 3 h_1(23)=23 \bmod 10 = 3 h1(23)=23mod10=3,位置 3 3 3 为空,直接插入。
  • 插入键 33 33 33 h 1 ( 33 ) = 33 m o d 10 = 3 h_1(33)=33 \bmod 10 = 3 h1(33)=33mod10=3,位置 3 3 3 已被占用, h 2 ( 33 ) = 7 − ( 33 m o d 7 ) = 7 − 5 = 2 h_2(33)=7-(33 \bmod 7)=7 - 5 = 2 h2(33)=7(33mod7)=75=2,进行第一次探测 i = 1 i = 1 i=1 h ( 33 , 1 ) = ( 3 + 1 × 2 ) m o d 10 = 5 h(33, 1)=(3+1\times2)\bmod 10 = 5 h(33,1)=(3+1×2)mod10=5,位置 5 5 5 为空,插入到位置 5 5 5
  • 插入键 43 43 43 h 1 ( 43 ) = 43 m o d 10 = 3 h_1(43)=43 \bmod 10 = 3 h1(43)=43mod10=3,位置 3 3 3 已被占用, h 2 ( 43 ) = 7 − ( 43 m o d 7 ) = 7 − 1 = 6 h_2(43)=7-(43 \bmod 7)=7 - 1 = 6 h2(43)=7(43mod7)=71=6,进行第一次探测 i = 1 i = 1 i=1 h ( 43 , 1 ) = ( 3 + 1 × 6 ) m o d 10 = 9 h(43, 1)=(3+1\times6)\bmod 10 = 9 h(43,1)=(3+1×6)mod10=9,位置 9 9 9 为空,插入到位置 9 9 9
3.优缺点
  • 优点:是开放寻址法中最好的方法之一,能更均匀地分布键,减少聚集现象,使插入、查找和删除操作的平均性能更接近理想情况。
  • 缺点:需要设计两个散列函数,实现相对复杂,计算开销也会稍微大一些。

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

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

相关文章

【双指针题目】

双指针 美丽区间&#xff08;滑动窗口&#xff09;合并数列&#xff08;双指针的应用&#xff09;等腰三角形全部所有的子序列 美丽区间&#xff08;滑动窗口&#xff09; 美丽区间 滑动窗口模板&#xff1a; int left 0, right 0;while (right < nums.size()) {// 增大…

为什么命令“echo -e “\033[9;0]“ > /dev/tty0“能控制开发板上的LCD不熄屏?

为什么命令"echo -e “\033[9;0]” > /dev/tty0"能控制开发板上的LCD不熄屏&#xff1f; 在回答这个问题前请先阅读我之前写的与tty和终端有关的博文 https://blog.csdn.net/wenhao_ir/article/details/145431655 然后再来看这条命令的解释就要容易些了。 这条…

嵌入式八股文面试题(一)C语言部分

1. 变量/函数的声明和定义的区别&#xff1f; &#xff08;1&#xff09;变量 定义不仅告知编译器变量的类型和名字&#xff0c;还会分配内存空间。 int x 10; // 定义并初始化x int x; //同样是定义 声明只是告诉编译器变量的名字和类型&#xff0c;但并不为它分配内存空间…

go-zero学习笔记(三)

利用goctl生成rpc服务 编写proto文件 // 声明 proto 使用的语法版本 syntax "proto3";// proto 包名 package demoRpc;// golang 包名(可选) option go_package "./demo";// 如需为 .proto 文件添加注释&#xff0c;请使用 C/C 样式的 // 和 /* ... */…

Javascript代码库-jQuery入门

摘自千锋教育kerwin的js教程 jQuery 是一个前端库&#xff0c;也是一个方法库他里面封装着一些列的方法供我们使用我们常用的一些方法它里面都有&#xff0c;我们可以直接拿来使用就行了jQuery 之所以好用&#xff0c;很多人愿意使用&#xff0c;是因为他的几个优点太强大了 优…

【25考研】南开软件考研复试复习重点!

一、复试内容 复试采取现场复试的方式。复试分为笔试、机试和面试三部分。三部分合计100分&#xff0c;其中笔试成绩占30%、机试成绩占30%、面试成绩占40%。 1.笔试&#xff1a;专业综合基础测试 考核方式&#xff1a;闭卷考试&#xff0c;时长为90分钟。 笔试考查内容范围…

【最长上升子序列Ⅱ——树状数组,二分+DP,纯DP】

题目 代码&#xff08;只给出树状数组的&#xff09; #include <bits/stdc.h> using namespace std; const int N 1e510; int n, m; int a[N], b[N], f[N], tr[N]; //f[i]表示以a[i]为尾的LIS的最大长度 void init() {sort(b1, bn1);m unique(b1, bn1) - b - 1;for(in…

012-51单片机CLD1602显示万年历+闹钟+农历+整点报时

1. 硬件设计 硬件是我自己设计的一个通用的51单片机开发平台&#xff0c;可以根据需要自行焊接模块&#xff0c;这是用立创EDA画的一个双层PCB板&#xff0c;所以模块都是插针式&#xff0c;不是表贴的。电路原理图在文末的链接里&#xff0c;PCB图暂时不选择开源。 B站上传的…

容器迭代器iterator

文章目录 1、自定义String实现iterator2、自定义vector实现iterator3、迭代器失效问题 迭代器的功能&#xff1a;提供一种统一的方式&#xff0c;来透明的遍历容器。 迭代器可以透明的访问容器内部的元素的值&#xff0c;而无需了解其底层遍历机制具体是数组的下标还是链表的指…

对象的实例化、内存布局与访问定位

一、创建对象的方式 二、创建对象的步骤: 一、判断对象对应的类是否加载、链接、初始化: 虚拟机遇到一条new指令&#xff0c;首先去检查这个指令的参数能否在Metaspace的常量池中定位到一个类的符号引用&#xff0c;并且检查这个符号引用代表的类是否已经被加载、解析和初始化…

传输层协议 UDP 与 TCP

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Linux 目录 一&#xff1a;&#x1f525; 前置复盘&#x1f98b; 传输层&#x1f98b; 再谈端口号&#x1f98b; 端口号范围划分&#x1f98b; 认识知名端口号 (Well-Know Port Number) 二&#xf…

实验十一 Servlet(二)

实验十一 Servlet(二) 【实验目的】 1&#xff0e;了解Servlet运行原理 2&#xff0e;掌握Servlet实现方式 【实验内容】 改造实验10&#xff0c;引入数据库&#xff0c;创建用户表&#xff0c;包括用户名和密码&#xff1a;客户端通过login.jsp发出登录请求&#xff0c;请求…

服务SDK三方新版中央仓库和私服发布详解

预备信息Github仓库发布Gradle版本匹配Gradle项目构建全局变量定义Gradle项目Nexus仓库配置与发布过程Gradle项目发布至Sonatype中央仓库配置过程总结当我们在实现一个项目技术总结、工具类封装或SDK封装,通常是为了方便开发者使用特定服务或平台而提供的一组工具和API。您可能…

git 新项目

新项目git 新建的项目如何进行git 配置git git config --global user.name "cc" git config --global user.email ccexample.com配置远程仓库路径 // 添加 git remote add origin http://gogs/cc/mc.git //如果配错了&#xff0c;删除 git remote remove origin初…

openmv的端口被拆分为两个 导致电脑无法访问openmv文件系统解决办法 openmv USB功能改动 openmv驱动被更改如何修复

我之前误打误撞遇到一次&#xff0c;直接把openmv的全部端口删除卸载然后重新插上就会自动重新装上一个openmv端口修复成功&#xff0c;大家可以先试试不行再用下面的方法 全部卸载再重新插拔openmv 要解决OpenMV IDE中出现的两个端口问题&#xff0c;可以尝试以下步骤&#x…

利用Python高效处理大规模词汇数据

在本篇博客中&#xff0c;我们将探讨如何使用Python及其强大的库来处理和分析大规模的词汇数据。我们将介绍如何从多个.pkl文件中读取数据&#xff0c;并应用一系列算法来筛选和扩展一个核心词汇列表。这个过程涉及到使用Pandas、Polars以及tqdm等库来实现高效的数据处理。 引…

LabVIEW双光子成像系统:自主创新,精准成像,赋能科研

双光子成像系统&#xff1a;自主创新&#xff0c;精准成像&#xff0c;赋能科研 第一部分&#xff1a;概述 双光子成像利用两个低能量光子同时激发荧光分子&#xff0c;具有深层穿透、高分辨率、低光损伤等优势。它能实现活体深层组织的成像&#xff0c;支持实时动态观察&…

Deepseek-R1 和 OpenAI o1 这样的推理模型普遍存在“思考不足”的问题

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

Vue3学习笔记-Vue开发前准备-1

一、安装15.0或更高版本的Node.js node -v npm -v 二、创建Vue项目 npm init vuelatest 三、Vue项目结构 node_modules: Vue项目运行的依赖文件public&#xff1a;资源文件夹package.json&#xff1a;信息描述文件

Denavit-Hartenberg DH MDH坐标系

Denavit-Hartenberg坐标系及其规则详解 6轴协作机器人的MDH模型详细图_6轴mdh-CSDN博客 N轴机械臂的MDH正向建模&#xff0c;及python算法_mdh建模-CSDN博客 运动学3-----正向运动学 | 鱼香ROS 机器人学&#xff1a;MDH建模 - 哆啦美 - 博客园 机械臂学习——标准DH法和改进MDH…