[Data Structure & Algorithm] 哈希表

哈希方法(Hashing) - 散列

  • 通过函数h将K映射到表T[0..M-1]的下标上,这样h(Ki)就是对应结点Ki的存储地址
    • 哈希表 - T
    • 哈希表长 - M
    • 哈希函数 - h
      • 冲突(Collision) - 两个不同的关键字,通过哈希函数映射到同一个地址
  • 优点 - 直接寻址查找,理想时间复杂度为O(1),但实际很难做到
  • 装填因子α = 哈希表中关键字的个数/哈希表的长度
    • α越小 -> 哈希表中的空地址越多 -> 发生冲突的可能性越小 -> 平均查找实践越小
  • 查询成功平均长度 = 查询成功的次数/关键字的个数
    • 如果没有冲突,则查询成功的次数 = 1
    • 如果为了解决而偏移过地址,则查询成功的次数 = 偏移量
  • 查询失败平均长度 = 查询失败的次数/关键字的个数
    • 如果是空地址,则查询失败的次数 = 1
    • 如果不是空地址,则查询失败的次数 = 从这个地址到最近的空地址的距离

哈希函数的构造

  • 要求

    • 尽量减少冲突
    • 哈希后的地址随机分布在整个地址区间
    • 以下方法可以搭配使用
  • 直接定址法

    • 通过线性计算, 如h(key) = a*key + b
    • 要求 - 关键字分布具有很强的规律性
    • 优点 - 不会产生冲突
  • 数据分析法

    • 选择随机性较强的部分作为地址,如对于8位数的集合,选择其中随机性较强的几位数,尽量构成不相同的地址
    • 要求
      • 关键字比较长
      • 关键字的形式已经确定
  • 平方取中法 - 较为常用

    • 先将关键字平方,再选择中间几位数作为地址
    • 优点 - 平方后保证关键字的每一位都有作用,减小冲突的可能性
  • 折叠法

    • 移位折叠法 - 将关键词分成几部分(每部分的位数可以不同),再相加
    • 边界折叠法
  • 除留余数法

    • 将关键字除以某个不大于哈希表表长m的数p后,取余数
    • p的选取
      • 一般设为小于哈希表长度的最大质数
      • 一般不设为2的次幂 - 增加冲突的可能性

解决冲突的办法

  • 开放定址法
    • 基本思路 - 对于冲突的两个关键字,将后一个关键字通过探测方法填入另一个地址中
    • 常用探测方法
      • 线性探测法 - 从已经被占用的地址i开始依次向下(i+1,i+2,i+3)探测,直到找到空的地址
      • 平方探测法 - 从已经被占用的地址i开始按平方数向下(i+1,i+4,i+9)探测,直到找到空的地址
        • 缺点 - 不易探测到整个散列空间
      • 双散列 - 有两个哈希函数h1, h2,当h1计算出的哈希值有冲突时,通过h2计算出的探测地址的增量h2(key),即从已经被占用的地址i开始从i+h2(key),i+2h2(key),i+3h2(key)探测,直到找到空的地址
        • 要求 - h2的值和M互素,为了使关键字较均匀地分布在整个哈希表中
    • 平均查找长度 - 1/2*(1+1/(1-α))
  • 链地址法
    • 基本思路
      • 将哈希表的每一个地址空间都定义为一个单链表的表头指针
      • 将对应相同哈希地址的关键字,链接在该地址的表头指针后
    • 优点
      • 处理冲突简单,平均查找时间较短
      • 删除结点简单
      • 不会溢出
    • 缺点 - 维护指针需要额外的空间
    • 适用
      • 无法确定长度
      • 结点规模较大
    • 平均查找长度 - 1+α/2
posted @ 2018-10-24 20:52  break大蜗牛  阅读(138)  评论(0编辑  收藏  举报