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

二、线性探测(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)=7−5=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)=7−1=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.优缺点
- 优点:是开放寻址法中最好的方法之一,能更均匀地分布键,减少聚集现象,使插入、查找和删除操作的平均性能更接近理想情况。
- 缺点:需要设计两个散列函数,实现相对复杂,计算开销也会稍微大一些。
相关文章:
深入理解开放寻址法中的三种探测序列
一、引言 开放寻址法是解决散列表中冲突的一种重要方法,当发生冲突(即两个不同的键通过散列函数计算得到相同的散列值)时,它会在散列表中寻找下一个可用的存储位置。而探测序列就是用于确定在发生冲突后,依次尝试哪些…...
图像噪声处理技术:让图像更清晰的艺术
在这个数字化时代,图像作为信息传递的重要载体,其质量直接影响着我们的视觉体验和信息解读。然而,在图像采集、传输或处理过程中,难免会遇到各种噪声干扰,如高斯噪声、椒盐噪声等,这些噪声会降低图像的清晰…...
linux运行级别
运行级别:指linux系统在启动和运行过程中所处的不同的状态。 运行级别之间的切换:init (级别数) 示例: linux的运行级别一共有7种,分别是: 运行级别0:停机状态 运行级别1:单用户模式/救援模式…...
深入剖析Electron的原理
Electron是一个强大的跨平台桌面应用开发框架,它允许开发者使用HTML、CSS和JavaScript来构建各种桌面应用程序。了解Electron的原理对于开发者至关重要,这样在设计应用时能更合理,遇到问题也能更准确地分析和解决。下面将从多个方面深入剖析E…...
C++ 游戏开发:完整指南
目录 什么是游戏开发? 为什么选择 C 进行游戏开发? C 游戏开发:完整指南 1. 理解游戏开发的基础 2. 学习游戏引擎 3. 精通 C 进行游戏开发 4. 学习数学在游戏开发中的应用 5. 探索图形编程 6. 专注于游戏开发的某一领域 7. 通过游戏项目进行实…...
WebForms SortedList 深度解析
WebForms SortedList 深度解析 引言 在Web开发领域,对于数据结构的理解与应用至关重要。其中,SortedList类在WebForms中是一个常用的数据结构,它能够帮助开发者高效地管理有序数据集合。本文将深入解析SortedList类在WebForms中的应用,包括其基本概念、常用方法、性能特点…...
【hot100】刷题记录(12)-回文链表
题目描述: 给你一个单链表的头节点 head ,请你判断该链表是否为 回文链表 。如果是,返回 true ;否则,返回 false 。 示例 1: 输入:head [1,2,2,1] 输出:true示例 2: …...
深入理解 Unix Shell 管道 Pipes:基础和高级用法 xargs tee awk sed等(中英双语)
深入理解 Unix Shell 管道(|) 1. 什么是管道(Pipe)? 管道(|)是 Unix/Linux Shell 中最强大的功能之一,它允许将一个命令的输出作为另一个命令的输入,从而实现数据流的处…...
[MySQL]事务的理论、属性与常见操作
目录 一、事物的理论 1.什么是事务 2.事务的属性(ACID) 3.再谈事务的本质 4.为什么要有事务 二、事务的操作 1.事务的支持版本 2.事务的提交模式 介绍 自动提交模式 手动提交模式 3.事务的操作 4.事务的操作演示 验证事务的回滚 事务异常…...
RS485接口EMC
A.滤波设计要点 L1为共模电感,共模电感能够衰减共模干扰,对单板内部的干扰以及外部的干扰都能抑制,能提高产品的抗干扰能力,同时也能减小通过485信号线对外的辐射,共模电感阻抗选择范围为120Ω/100MHz ~2200Ω/100MHz…...
快速上手mybatis教程
基础知识 MyBatis 是一款优秀的持久层框架,其核心组件主要包括以下部分: SqlSession 作用:SqlSession 是 MyBatis 的核心接口,负责与数据库进行通信,执行 SQL 语句,并返回查询结果。它是 MyBatis 的一次会…...
本地部署DeepSeek-R1保姆级教程
近期,我国一款开源模型 DeepSeek-R1以低成本和高性能震撼了全球科技界。该模型的开源性使开发者能够在本地环境中部署和运行,提供了更高的灵活性和控制力。如果你也想在本地部署 DeepSeek-R1,可以参考以下完整的教程,涵盖Mac 版本…...
blender 相机参数
目录 设置相机参数: 3. 设置相机参数示例 4. 相机透视与正交 5. 额外的高级设置 设置相机参数: 设置渲染器: 外参转换函数 转换测试代码: 获取blender渲染外参: 设置相机参数: 3. 设置相机参数示…...
在GPIO控制器中,配置通用输入,读取IO口电平时,上拉和下拉起到什么作用
上下拉电阻作用 在通用输入的时候,也就是在读某个IO的电平的时候 一定要让IO口先保持一个电平状态,这样才能检测到不同电平状态。 如何保持电平状态? 1. 可以通过芯片内部的上下拉电阻,由于是弱上下拉一般不用 2. 硬件外界一个…...
Maven工程核心概念GAVP详解:从命名规范到项目协作的基石
Maven工程核心概念GAVP详解:从命名规范到项目协作的基石 一、GAVP是什么? 在Maven工程中,GAVP是四个核心属性的缩写:GroupId、ArtifactId、Version、Packaging。这组属性为项目在Maven仓库中提供了唯一标识,类似于“项…...
如何利用DeepSeek打造医疗领域专属AI助手?从微调到部署全流程解析
如何利用DeepSeek开源模型打造医疗领域专属AI助手?从微调到部署全流程解析 医疗人工智能正迎来爆发式增长,但在实际应用中,通用大模型往往存在医学知识不精准、诊断逻辑不严谨等问题。本文将手把手带您实现医疗垂直领域大模型的定制化训练&a…...
Redis|前言
文章目录 什么是 Redis?Redis 主流功能与应用 什么是 Redis? Redis,Remote Dictionary Server(远程字典服务器)。Redis 是完全开源的,使用 ANSIC 语言编写,遵守 BSD 协议,是一个高性…...
眼见着折叠手机面临崩溃,三星计划增强抗摔能力挽救它
据悉折叠手机开创者三星披露了一份专利,通过在折叠手机屏幕上增加一个抗冲击和遮光层的方式来增强折叠手机的抗摔能力,希望通过这种方式进一步增强折叠手机的可靠性和耐用性,来促进折叠手机的发展。 据悉三星和研发可折叠玻璃的企业的做法是在…...
Leetcode面试高频题分类刷题总结
https://zhuanlan.zhihu.com/p/349940945 以下8个门类是面试中最常考的算法与数据结构知识点。 排序类(Sort): 基础知识:快速排序(Quick Sort), 归并排序(Merge Sort)的…...
Vue.js `v-memo` 性能优化技巧
Vue.js v-memo 性能优化技巧 今天我们来聊聊 Vue 3.2 引入的一个性能优化指令:v-memo。如果你在处理大型列表或复杂组件时,遇到性能瓶颈,那么 v-memo 可能会成为你的得力助手。 什么是 v-memo? v-memo 是 Vue 3.2 新增的内置指…...
CDN 报错 403/502/504 怎么解决?源站与防护策略排查
网站接入CDN后,原本访问流畅,突然出现403、502、504报错,用户反馈无法访问,自己排查半天找不到头绪——其实这类报错大多和「源站状态」「防护策略」「CDN配置」三个环节相关,今天就结合实操经验,把这三种常…...
远程收款好用服务商
在数字化支付日益普及的今天,远程收款成为许多商家和创业者的重要需求。然而,由于各种风控限制,微信支付、支付宝等主流支付平台在异地收款时常常出现异常提示或风险拦截,给用户带来了不少困扰。本文将对比分析几家提供远程收款服…...
菊水PBZ40可编程电源RS232C通信协议实战指南
1. 认识菊水PBZ40可编程电源 如果你正在实验室里捣鼓自动化测试系统,大概率会遇到需要精确控制电源输出的场景。菊水PBZ40就是这样一款专业选手,它不仅能提供稳定的直流输出,还能模拟各种交流波形信号。我第一次接触这台设备时,就…...
OpenClaw多模型对比:ollama-QwQ-32B与云端API在自动化任务中的表现
OpenClaw多模型对比:ollama-QwQ-32B与云端API在自动化任务中的表现 1. 测试背景与实验设计 去年冬天,当我第一次尝试用OpenClaw自动化处理堆积如月的合同文件时,面对本地部署和云端API两种选择,陷入了典型的"技术选择困难症…...
【模型手术室】第九篇:多模态微调 —— 让模型学会“看图说话”:从像素到行业认知的飞跃
专栏进度:09 / 10 (微调实战专题) 如果你使用的是 LLaVA、Qwen2-VL 或 DeepSeek-VL,它们原生具备识别猫狗和常识图片的能力。但如果你给它一张半导体无尘车间的传感器拓扑图,它大概率会胡言乱语。多模态微调的目标,就是建立“视觉…...
雯雯的后宫-造相Z-Image-瑜伽女孩实战教程:结合ControlNet实现精准体式控制
雯雯的后宫-造相Z-Image-瑜伽女孩实战教程:结合ControlNet实现精准体式控制 1. 从零开始:环境准备与模型部署 想要生成专业的瑜伽女孩图片,首先需要搭建好环境。雯雯的后宫-造相Z-Image-瑜伽女孩是一个专门针对瑜伽场景优化的文生图模型&am…...
lite-avatar形象库部署教程:GPU共享模式下多租户数字人服务隔离方案
lite-avatar形象库部署教程:GPU共享模式下多租户数字人服务隔离方案 1. 项目概述 lite-avatar形象库是一个专业的数字人形象资产管理平台,基于HumanAIGC-Engineering/LiteAvatarGallery构建。这个库提供了150经过预训练的2D数字人形象,专门…...
KittenTTS终极指南:如何在CPU上实现25MB轻量级TTS语音合成
KittenTTS终极指南:如何在CPU上实现25MB轻量级TTS语音合成 【免费下载链接】KittenTTS State-of-the-art TTS model under 25MB 😻 项目地址: https://gitcode.com/gh_mirrors/ki/KittenTTS KittenTTS是一款革命性的轻量级文本转语音工具&#…...
手把手教你为本地LLM(Llama/Qwen)实现打字机式流式输出,Gradio+Transformers保姆级教程
手把手教你为本地LLM实现打字机式流式输出:Gradio与Transformers深度整合指南 当我们在本地部署大语言模型时,最令人沮丧的体验莫过于盯着进度条等待完整响应。想象一下这样的场景:你向模型提出一个复杂问题,屏幕陷入长达十几秒的…...
2025年Cursor免费续杯终极指南:绕过限制的自动化方案
1. 为什么需要Cursor免费续杯方案 作为一个长期使用AI编程工具的老用户,我完全理解学生和独立开发者面临的困境。Cursor作为一款优秀的AI编程助手,确实能大幅提升开发效率,但每月150次的免费额度对于项目开发来说实在捉襟见肘。特别是在调试和…...
