哈希散列(HASH)原理

来源:互联网 发布:sai mac 打不开 编辑:程序博客网 时间:2024/05/29 13:30

散列的基本概念

散列(hash table)是普通数组概念的延伸,它的出现是为了实现快速的插入,删除,查询等功能(字典操作)的数据结构。在数据查找功能中平均时间复杂度为O(1)。

Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。

在散列表中,不是直接把关键字作为下标,而是根据关键字计算出相应的下标。

直接寻址
直接寻址是将所有的关键字放在一个数组内,但这种方式局限于关键字比较少的时候,否则会浪费掉大量的存储空间。
所以当实际存储的关键字比全部的可能关键字总数要小时,散列可以有效的代替数组。

HASH表的原理

散列表是通过散列函数h,将关键字映射到散列表中,从而减小了数组下标的范围。
这里写图片描述

散列函数:

散列应尽可能被等可能得散列开来(少冲突),并且和其他已散列的关键字散列到哪儿无关。当散列的关键字不是自然数时,就需要将他们转化为自然数。
常用的散列方法。
1>.除法散列法:
通过取k除以m的余数,将关键字k映射到m个空间内
函数表达式为: h(k) = k mod m
使用注意:m值的选择:不应为2的幂,而可以设置成2一个不太接近2的整数幂的素数。

2>.乘法散列法
乘法散列包含2个步骤:
第一步:用关键字k乘上常数A(A在0-1中间),并提取k*A的小数部分。第二步:用m乘上这个值,然后向下取整。
函数表达式为: h(k) = [m(kA mod 1)]
改方法对m的要求不高,一般选为2的某个幂次。

3>.全域散列
全域散列法是在执行的一开始,就从一组精心设计的函数中,随机挑选一个作为散列函数。该方法仅当编译器选择了一个随机的散列函数,使得标识符的散列效果较差是才会出现较差的性能。

冲突:当两个关键字映射到同一个位置时,则会发生冲突。
散列的平均性能取决于所采用的的散列函数h,及分布的均匀程度。
解决散列冲突的方法
1>.链接法:
将散列的槽中放入链表,链表连接冲突的关键字。
2>.开放寻址法:
开放寻址法要求所有的元素都在散列表里。即每个表项或包含动态集合的一个元素,或者为空。
注:该方法不能存放超过散列表设定的大小