数据结构——五十二、散列函数的构造(王道408)

文章目录

前言

本文总结了设计散列函数的注意事项和常用方法。设计散列函数时需注意:定义域覆盖所有关键字、值域不越界、减少冲突、计算简单。主要方法包括:除留余数法(取不大于表长的最大质数)、直接定址法(适用于连续关键字)、数字分析法(选取分布均匀的数码位)、平方取中法(取平方值的中间位)。其中重点阐述了除留余数法对质数取余可减少冲突的原因,并通过具体示例说明了各方法的适用场景和实现要点。这些方法可根据关键字特性选择使用,以达到均匀分布和高效存储的目的。

一.设计散列函数时应该注意什么

  1. 定义域必须涵盖所有可能出现的关键字。

    反例: H ( k e y ) = k e y    %    13 H(key)=\sqrt{key} \;\%\;13 H(key)=key %13,不支持关键字为负值

  2. 值域不能超出散列表的地址范围。

    反例: H ( k e y ) = k e y    %    15 H(key)=key\;\%\;15 H(key)=key%15,可能被映射到非法地址13、14

  3. 尽可能减少冲突。散列函数计算出来的地址应尽可能均匀分布在整个地址空间。

    反例: H ( k e y ) = ( k e y × 13 )    %    13 H(key)=(key×13)\;\%\;13 H(key)=(key×13)%13任何关键字都会被映射到地址0

  4. 散列函数应尽量简单,能够快速计算出任意一个关键字对应的散列地址。

    反例: H ( k e y ) = ( k e y ! )    %    13 H(key)=(key!)\;\%\;13 H(key)=(key!)%13,若关键字值较大,计算阶乘耗时高

二.除留余数法

1.思路和使用场景

  • 除留余数法------ H ( k e y ) = k e y    %    p 除留余数法------H(key)=key\;\%\;p 除留余数法------H(key)=key%p
    散列表表长为m,取一个不大于m但最接近或等于m的质数p
    注:质数又称素数。指除了1和此整数自身外,不能被其他自然数整除的数
  • 适用场景:较为通用,只要关键字是整数即可

2.具体例子

  • 例1:散列表表长 m=13。13是质数,因此可令散列函数 H(key)=key%13
  • 例2:散列表表长 m=15。不大于15且最接近15的质数是13,因此可令散列函数 H(key)=key%13

3.拓展:为什么除留余数法要对质数取余?

1.原因

  • 原因:对质数取余,可以分布更均匀,从而减少冲突

2.具体例子

  • 设:可能出现的关键字={2,4,6,8,10,12,14}
  1. 散列表表长8,散列函数H(Key)=key%8
  • 对合数取余,散列地址分布不均匀,易发生冲突
  1. 散列表表长8,散列函数H(Key)=key%7
  • 对质数取余,散列地址分布均匀,不易发生冲突

Why?------取余运算会被"公因子"影响,详见《数论》

三.直接定址法

1.思路与使用场景

  • 直接定址法------ H ( k e y ) = k e y 或 H ( k e y ) = a ∗ k e y + b H(key)=key或H(key)=a*key+b H(key)=key或H(key)=a∗key+b
    其中,a和b是常数。这种方法计算最简单,且不会产生冲突。若关键字分布不连续,空位较多,则会造成存储空间的浪费。
  • 适用场景:关键字分布基本连续

2.具体思路

  • 例:用散列表存储某班级的30个学生信息,班内学生学号为(1120112176~1120112205)
  • 可令 H(key) = key - 1120112176

四.数字分析法

1.思路与使用方法

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

2.具体例子

  • 例:要求将手机用户的信息存入长度为 10000 的散列表。以"手机号码"作为关键字设计散列函数
    1. 中国移动联通电信前三位电话号码各不一样,中间的四位通常是地区的区号,而末尾的四位每个人的电话号码就各不相同
    2. 所以以手机号码作为关键字的话,那前边的这七个数码位,这些值的分布是不均匀的,只有末尾的四个数码位它的分布是相对均匀的,那我们可以直接选取末尾的四位作为散列地址

五.平方取中法

1.思路与使用方法

  • 平方取中法------取关键字的平方值的中间几位作为散列地址。
    具体取多少位要视实际情况而定。这种方法得到的散列地址与关键字的每位都有关系,因此使得散列地址分布比较均匀。
  • 适用场景:关键字的每位取值都不够均匀。

2.具体例子

  • 例:某汽车品牌,以(底盘号、发动机号、外观号)作为一款汽车型号的标识。该品牌有100种车型,欲将这些车型信息存入长度为100的散列表,如何设计散列函数?
    1. 先对关键字取平方
    2. 我们取平方的中间两个数值位作为散列地址
  • 原因是在乘方的时候最中间的两位元素会受到其它所有元素的影响,在这种情况下,最中间的两位元素最终会分布的相对均匀

六.知识回顾与重要考点

结语

八更😉
如果想查看更多章节,请点击:一、数据结构专栏导航页

相关推荐
智者知已应修善业15 小时前
【求中位数】2024-1-23
c语言·c++·经验分享·笔记·算法
张人玉15 小时前
百度 AI 图像识别 WinForms 应用代码分析笔记
人工智能·笔记·百度
地平线开发者15 小时前
PTQ 量化数值范围与优化
算法·自动驾驶
sali-tec15 小时前
C# 基于halcon的视觉工作流-章68 深度学习-对象检测
开发语言·算法·计算机视觉·重构·c#
测试人社区-小明16 小时前
智能弹性伸缩算法在测试环境中的实践与验证
人工智能·测试工具·算法·机器学习·金融·机器人·量子计算
xqqxqxxq16 小时前
背单词软件技术笔记(V1.0核心版及V2.0随机挖字母)
笔记
罗西的思考16 小时前
【Agent】MemOS 源码笔记---(5)---记忆分类
人工智能·深度学习·算法
YJlio17 小时前
Active Directory 工具学习笔记(10.8):AdInsight——保存与导出(证据留存、共享与二次分析)
数据库·笔记·学习
xqqxqxxq17 小时前
背单词软件技术笔记(V2.0扩展版)
java·笔记·python
paceboy17 小时前
Claude和Cursor之间的切换
人工智能·程序人生