数据结构与Python算法——哈希算法

本文介绍了四种常见的哈希算法(除法、乘法、平方取中和随机数),以及开放定址法中的线性探查法、二次探查法和链地址法来处理哈希冲突。这些技术在IT中用于高效地将关键字映射到数组位置,尽管存在冲突问题,但通过恰当的选择和设计,可以优化数据结构的性能。
摘要由CSDN通过智能技术生成

哈希函数

  • 除法哈希算法
    • 用一个关键字去除以一个特定的质数,所得的余数就是该关键字的哈希值。通过 x 除以 m 的余数将关键字映射到数组的 m 个位置中。哈希函数公式为 h(x) = x mod m。注意,在选择 m 的值时,尽量选择质数,免得出现过多的多个关键字映射到同一个位置的情况,降低哈希函数的效率。
  • 乘法哈希算法
    • 对给定的长度为 m 的数组,用关键字 x 乘以一个常数 N,N 的值为大于 0 并小于 1 的一个小数,并提取出 Nx 的小数部分。之后,用 m 乘以这个小数,再向下取整。
      1. 哈希函数公式为 h(x) = ⌊ m (Nx mod 1)⌋
      2. 其中 Nx mod 1 的意思就是 Nx 的小数部分。
      3. 相对于除法哈希算法,乘法哈希算法对于数组的长度 m 没有过多的要求。研究表明,N 的值为 0.618 较好。
  • 平方取中法
    • 首先计算出关键字的平方值,然后取平方值中间几位作为哈希地址。
  • 随机数哈希算法
    • 选择一个随机函数,以关键字作为随机函数的种子,然后以随机函数的返回值作为该关键字的哈希值。通常情况下,当关键字的长度不等且不规则时采用这种方法。

在使用哈希算法时,第一步是用哈希函数将关键字转化为数组的一个索引。理想情况下,不同的关键字都能转化为不同的哈希值。当然,这只是理想情况,所以我们需要面对两个或多个关键字都映射到相同的哈希值的情况。因此,哈希算法的第二步就是一个处理冲突的过程。
解决哈希冲突的方法有很多种,如开放定址法、链地址法、二次再散列法、线性探测再散列等方法。

  1. 开放定址法
    所谓开放定址法,就是当一个关键字插入到哈希表中遇到冲突时,可以连续地检查哈希表的各个位置,直到找到一个空位置把数据插入进去为止。有三种开放定址法:
    • 线性探查法
      1. 线性探查法的思想非常简单,对每一个关键字 x,通过哈希函数得到的哈希值为 key,那么当发生冲突时,依次查看 key+1,key+2,直到 key+m-1,然后循环到哈希表的第0位,第1位,…,直到查询到某一个位置为空,把关键字存储到该位置即可。
      2. 线性探查法相对比较容易实现,只需要顺着哈希表的顺序查找即可。但是,线性探查法也存在一个问题,随着数据存储的越来越多,数据很容易聚集起来,那么平均查找时间也会随着不断增加。
    • 二次探查法
      • 二次探查法和线性探查法类似,改变的只是每次探查的偏移量,以 i 的二次方的方式进行变化。探查时从地址 key 开始,首先探查 key,然后依次探查 key+1, key+4,key+9,…,直到探查到有空余的位置为止。
  2. 链地址法
    • 链地址法处理冲突的方法本质上是一种数组加链表的处理方法。当发生多个数据通过哈希函数映射后得到相同的哈希值时,通常把具有相同哈希地址的关键字放在同一个链表中,该链表称为同义词链表或桶。
    • 当把相同哈希地址的关键字数据都放在同一个链表中时,有 N 个哈希地址就有 N 个链表。同时,用数组 Hash[0… N-1]存放每个链表的头指针,之后把哈希地址为 i 的数据全部以节点的方式插入对应的链表里。
    • 链地址法存储数据的过程是这样的,首先建立一个数组存储所有链表的头指针,由数据的关键字 key 通过对应的哈希函数计算出哈希地址,找到相应的桶号,之后建立新的节点存储该数据,并把节点放到桶内链表的最后面或者最前面。
    • 和存储数据的方法类似,查找数据的时候,也是由数据的关键字通过哈希函数计算关键字对应的哈希地址,之后顺序比较桶的内部节点是否与所查找的关键字一样,直到找到数据为止。如果全部节点都不和关键字一样,则说明哈希表里没有该数据。这个解决冲突的方法对哈希函数的要求很高,如果哈希函数选的不太好的话,哈希表的查找效率会退化为链表的查找,也就是顺序查找。
    • 用链地址法构造的散列表,插入和删除节点操作易于实现,所以构造链表的时间开销很低,但是指针需要开辟额外的地址空间,当数据量很大时,会扩大哈希表规模,内存空间需求较大。
  • 37
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值