关于hash的那点事儿

来源:互联网 发布:太极循环人工智能 编辑:程序博客网 时间:2024/06/05 11:34

hash的由来

为了解决规模很大,查找亦很频繁的问题,模仿数组,通过数组的起始位置和下标就能找到要查找的元素,不需要通过比较,所需的代价就是o(1)。基于借鉴数组查找元素的思想,由此产生了hash。

基本思想

首先在关键字key和记录的存储位置p之间创建一个对应关系H,使得p=H(key),H被称为哈希函数,p被称为散列地址。当创建hash表时,吧关键字为可以的记录放到地址为H(key)的存储空间中,以后查找关键字为key的记录时,在丽影hash函数就可以直接计算出记录的散列地址p,从而达到直接存储的目的。

构造hash函数的方法

  • 除留余数法
    用记录的值对小于或者等于边长m的最大素数取余。即H(key)=key%p
    假设长度为11,那么H(key)=key%11

  • 数字分析法
    假设有如下几位数:
    49646542 49673242 49687422经过分析可以发现关键字第4到6位分布比较均匀,所以可以取H(key)=d4d5d6

  • 平方取中法
    通过求关键字的平方值扩大相近数的差别,然后根据表长取其中一部分座位hash的函数值。有一组数0100,0110,1010,将他们每个平方以后得0010000,0012100,1020100,假设表长1000,则可取中间的三位数作为散列地址,即100,121,201

  • 分段叠加法
    将数分为位数相同的几部分,然后进行叠加。key=926483,H(key)=926+384=1310(折叠叠加方式)或者H(key)=926+483=1419.。要保证位数相同所以去除最高位。H(key)=310或419

  • 基数转换法
    将关键字看成是某一种进制的数,然后在转换成原来进制的数,在选择其中几位作为散列地址。比如12(13)=2*13^0+1*13^1=15(10),假设表长100,取低两位就好。

hash函数的冲突解决

开放定址法(再散列法)

  • 线性探测再散列
    如果当前位置有冲突,就看下一个;下一个还有冲突继续看下一个。现有一集合19,01,23,14,55,68,11,82,36
    存储过程如下
    这里写图片描述
    平均查找长度=(4*1+2*2+3+5+6)/9=22/9
  • 二次探测再散列
    冲突发生时分别在表的右左进行跳跃式的探测。d=1^2,(-)1^2,2^2,(-2)^2…K^2,(-k)^2
    过程如下
    这里写图片描述
    平均查找长度=(5*1+2*2+4+3)/9=16/9
  • 随机探测再散列
    建立随机数发生器,并给定一个随机数作为起始点

链地址法

把所有具有地址冲突的关键字用链表连接起来。现有关键字集合{1,2,3,4,5},表长为3,建立如下表
这里写图片描述
解决冲突后为
这里写图片描述
平均查找长度为(3*1+2*2)/5=1.4