C/C++算法——散列表

1、散列表介绍

  • 散列表的英文叫Hash Table,我们平时也叫它哈希表或者Hash 表。散列表用的是数组支持按照下标随机访问数据 的特性,所以散列表其实就是数组的一种扩展 ,由数组演化而来。可以说,如果没有数组,就没有散列表。

  • 散列表是算法在时间和空间上作出权衡的例子,它介于两个极端之间:

    • 如果没有内存限制 ,我们可以直接将键作为一个(可能非常庞大)数组索引,那么查找操作只需要一次
    • 如果没有时间限制,我们可以使用无序数组并进行顺序查找,这样就只需要很少的内存。
  • 使用散列的查找算法分为两步。

    • 第一步是用散列函数 将被查找的键转化为数组的一个索引(可能出现哈希碰撞,即不同的键可以转化为相同的索引值)
    • 第二步是处理碰撞冲突的过程。有两种常用的解决方法:拉链法线性探测法(开放寻址法的一种)

2、散列函数

  • 散列函数的定义
    • 一个把查找表中的关键字映射成该关键字对应的地址的函数,记为 Hash(key)=Addr(这里的地址可以是数组下标、索引或内存地址等)。
  • 散列函数的构造方法
    • 直接定址法

      直接取关键字的某个线性函数值为散列地址,散列函数为:H(key)=keyH(key)=a*key±b。式中,ab 是常数。这种计算方法简单且不会发生冲突。但只适合关键字的分布基本连续的情况。

    • 除留余数法

      这是一种同样简单、最常用的方法,假定散列表表长为m,取一个不大于m但最接近或等于m的质数p,散列函数为:H(key)=key%pH(key)=key MOD pMOD是取模运算符)模p为最接近m的质数时造成冲突的可能性最小。

    • 数字分析法

      比如学号一个班的同学前几位都是2022030XX,后两位每种数码(0,1,2...)出现的机会均等,此时应选取数码分布较为均匀的若干位作为散列地址。该方法适合于已知关键字集合,若更换了关键字(身份号),则需要重新构造新的散列函数。

    • 其他

      • 浮点数:例如将键转换为二进制再使用除留余数法。
      • 字符串:例如将键转换为大整数(例如把字符串当作N位的R进制值),然后再使用除留余数法。
      • 组合键。
      • 自定义的hashCode方法。
      • ...

3、哈希碰撞的处理

  • 基于拉链法的散列表
    散列表中,每个桶(bucket)或者槽(slot)会对应一条链表,所有散列值相同的元素我们都放到相同槽位对应的链表中:

  • 线性探测(Linear Probing)
    • 插入:如果某个数据经过散列函数散列之后,存储位置已经被占用了,我们就从当前位置开始,依次往后查找,看是否有空闲位置,直到找到为止。

    • 查找 :过程和插入一样,找到对应数组下标后,对比x与数组中存储的值是否相等,若不等则依次往后查找...

    • 删除 :删除的元素,特殊标记为 deleted。当线性探测查找的时候,遇到标记为 deleted 的空间,并不是停下来,而是继续往下探测。

4、参考文献

  1. 数据结构☞散列表
  2. 散列(Hash)表
  3. 算法(第四版) 3.4散列表
相关推荐
游是水里的游3 分钟前
【算法day19】回溯:分割与子集问题
算法
不想当程序猿_4 分钟前
【蓝桥杯每日一题】分糖果——DFS
c++·算法·蓝桥杯·深度优先
graceyun6 分钟前
C语言初阶习题【9】数9的个数
c语言·开发语言
cdut_suye15 分钟前
Linux工具使用指南:从apt管理、gcc编译到makefile构建与gdb调试
java·linux·运维·服务器·c++·人工智能·python
南城花随雪。23 分钟前
单片机:实现FFT快速傅里叶变换算法(附带源码)
单片机·嵌入式硬件·算法
dundunmm38 分钟前
机器学习之scikit-learn(简称 sklearn)
python·算法·机器学习·scikit-learn·sklearn·分类算法
古希腊掌管学习的神39 分钟前
[机器学习]sklearn入门指南(1)
人工智能·python·算法·机器学习·sklearn
波音彬要多做40 分钟前
41 stack类与queue类
开发语言·数据结构·c++·学习·算法
捕鲸叉41 分钟前
C++软件设计模式之外观(Facade)模式
c++·设计模式·外观模式
Schwertlilien2 小时前
图像处理-Ch5-图像复原与重建
c语言·开发语言·机器学习