• 开放寻址法


    Open addressing

    开放寻址法

    前面学习了一种最简单的冲突解决方法:链接法,现介绍另一种冲突解决方法:开放寻址法

    开放寻址法关键在于计算探查序列(probe sequence)

    • 对于每一个要插入的关键字k,显然需要连续地检查散列表以找到一个空槽,这个过程称为探查(probe)
    • 一个探查序列其实就是m个插槽号的一次排列(permutation)
    • 每个关键字的探查序列不同(哈希函数h接收两个参数:关键字 k 和探查号 trial count )
    • 显然探查序列包括了所有插槽,因此只要表中还有空槽就一定能被找到

    tips:对于同一个关键字k而言,其插入/搜索/删除的探查序列均一致

    Insert

    • 要插入关键字k,沿着k的探查序列寻找
    • 当找到一个空槽,插入k
    • 如果遍历结束 i==m,说明表满,插入失败
    • 对于搜索k而言,同样沿着探查序列搜索
    • 如果k在表中,就一定能顺着探查序列找到它
    • 否则,如果找到空槽或者遍历结束 i==m,这均说明k根本就没有被插入到表中(不考虑插入后又删除的情况),搜索失败

    Delete

    • 同理沿着探查序列查找k

    • 如果没有找到,返回错误

    • 当找到k所在槽 i 时,注意这时不能直接将槽 i 置为NIL,因为这会导致上面的搜索算法出错;

      正确的做法是:为槽 i 设定一个特定的值DELETED替代NIL来标记这个槽的内容被删除了,这样只需要对insert操作稍加修改,让其知道DELETED意味着槽为空,而对于search操作则无需再做什么改动

    Uniform Hashing Assumption

    均匀哈希假设:对于每一个关键字 k,在其对应的 m!个探查序列中,每个探查序列的生成概率相同

    (Double Hashing时可以这么假设)

    Analysis:

    假设已经插入了n个元素至m个插槽中,那么下一次插入预计的probe次数将<=1/(1-α)

    Proof:

    当插入一个新的元素时,记 p = (m-n)/m

    • 一次成功的概率为 p

    • 第一次失败的概率为 n/m

    • 第二次失败的概率为 (n-1)/(m-1)

    • 第三次失败的概率为 (n-2)/(m-2)

      ...

    • 以此类推,总共需要的探测次数为:
      $$
      Probes = 1+n/m(1+(n-1)/(m-1)(1+(n-2)/(m-2)(..(1+1/n-m+1)..))
      ≤1+α2+α3+....
      =sum_{i=0}∞αi
      =1/(1-a)

      $$

      根据上述推导过程,可以得出在均匀哈希假设下,搜索/插入/删除的时间复杂度均为 O(1/(1-α))

      image-20210627192258066

    参考:https://www.cnblogs.com/soyscut/p/3390032.html

  • 相关阅读:
    trim标签:可以自定义字符串的截取规则
    登录框(用获取value值方法)
    C++在ARM Linux下的交叉编译
    happybase导入报错:thriftpy.parser.exc.ThriftParserError: ThriftPy does not support generating module with path in protocol 'c'
    Nginx报错总结
    ubuntu安装Nginx
    mqtt在debian strench 9 docker环境下的搭建
    evokly/kafka-connect-mqtt 不支持kafka集群部署
    树莓派mqtt安装
    kafka和mqtt的区别和联系
  • 原文地址:https://www.cnblogs.com/potofsalt/p/14941814.html
Copyright © 2020-2023  润新知