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散列表
相关推荐
不去幼儿园21 小时前
【启发式算法】灰狼优化算法(Grey Wolf Optimizer, GWO)详细介绍(Python)
人工智能·python·算法·机器学习·启发式算法
随意起个昵称21 小时前
【二分】洛谷P2920,P2985做题小记
c++·算法
没书读了21 小时前
计算机组成原理-考前记忆清单
线性代数·算法
Hcoco_me21 小时前
大模型面试题5:矩阵(M*M)特征值分解的步骤
算法·机器学习·矩阵
望眼欲穿的程序猿21 小时前
Win系统Vscode+CoNan+Cmake实现调试与构建
c语言·c++·后端
lzh200409191 天前
【C++STL】List详解
开发语言·c++
luoyayun3611 天前
Qt/C++ 线程池TaskPool与 Worker 框架实践
c++·qt·线程池·taskpool
喵个咪1 天前
ASIO 定时器完全指南:类型解析、API 用法与实战示例
c++·后端
非著名架构师1 天前
极端天气下的供应链韧性:制造企业如何构建气象风险防御体系
大数据·人工智能·算法·制造·疾风气象大模型·风光功率预测
星轨初途1 天前
数据结构排序算法详解(2)——选择排序(附动图)
c语言·数据结构·经验分享·笔记·b树·算法·排序算法