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散列表
相关推荐
长潇若雪10 分钟前
《STL 六大组件之容器篇:简单了解 list》
开发语言·c++·经验分享·list·类和对象
君义_noip28 分钟前
信息学奥赛一本通 1524:旅游航道
c++·算法·图论·信息学奥赛
烁34737 分钟前
每日一题(小白)动态规划篇5
算法·动态规划
辰熤✔37 分钟前
MQTT报文类型
c语言·网络
独好紫罗兰38 分钟前
洛谷题单2-P5717 【深基3.习8】三角形分类-python-流程图重构
开发语言·python·算法
滴答滴答嗒嗒滴44 分钟前
Python小练习系列 Vol.8:组合总和(回溯 + 剪枝 + 去重)
python·算法·剪枝
学习同学1 小时前
C++进阶知识复习 1~15
java·开发语言·c++
egoist20231 小时前
【C++指南】一文总结C++二叉搜索树
开发语言·数据结构·c++·c++11·二叉搜索树
lidashent1 小时前
数据结构和算法——汉诺塔问题
数据结构·算法
小王努力学编程1 小时前
动态规划学习——背包问题
开发语言·c++·学习·算法·动态规划