代码改变世界

hash习

2011-08-04 22:20  justvi  阅读(171)  评论(0编辑  收藏  举报

1.什么是散列:

一种高效的数据存储与检索技术,普通数组概念的推广,散列表不把关键值作为数组下标,而是通过设计好的散列函数,将关键值映射到数组下标范围内的一个索引值,通过这个索引值来完成对值的插入、查找、删除等操作。

实际情况中,因为散列表的下标范围通常小于实际存储的数据量,所以难免出现不同的关键值散列到同一个索引位置的情况,这时就称发生了冲突,解决冲突可以通过两个方法来进行:

  1. 设计好的散列函数,能将关键字均匀的散列到表中;
  2. 采用某种冲突解决方法

2.散列函数

简单一致散列假设:任何关键字散列到表中每个位置的可能性是相同的,且散列到某个位置的可能性与其他关键字是独立无关的

将关键字转换为数字:为什么要这样做呢,因为计算索引值时通常是对数字来进行的,而关键字可能是字符串等复杂的数据结构,所以必须通过某种转换将其解释为数字来进行后续计算。

  1. 除法散列:h(k) = k mod m;
    其中m的选取很关键,m不宜为2的幂,常选取为与2的整数幂不太接近的常数
  2. 乘法散列: h(k) = m(kA mod 1) (小于此值的最大整数)
    m一般为2的某个幂,A是大于0小于1的某个常数
  3. 全域散列:在一组散列函数中随机的选取一个,使之独立于要存储的关键字,随机化保证了没有哪一种输入会始终导致最坏情况性态,同时对于不同时刻的同一样的输入,每次执行时的性态也是不一样的

3.冲突解决

链接法

链接法中,当发生不同的关键字散列到同一个索引位置时,将其放到一个链表中,通过在链表头执行插入操作来进行。在简单一致散列假设下,采用链接法解决冲突的散列表一次不成功查找和一次成功查找的期望时间为O(1+a) (a=n/m一个链中平均节点数)

开放寻址法

在开放寻址法中,当到来一个对于某个关键字的某种请求时(插入、查找、删除),按照某散列函数计算的探测序列对表中的相应位置上的状态与请求进行匹配,当符合请求时,执行相应的操作。

当执行查找时,在探测序列各节点上进行以下操作:若节点key与查找的key相同,则返回节点;若节点未存储元素,则返回;若以前存储过但已被删除,则探测下一个序列节点直到找到或为空。

插入操作基于查找,对于查找返回的结果要么为空要么匹配到了,对于空的,则在此位置插入,匹配的则更新节点的属性。

删除时不能直接删除查找到的元素,因为如果直接删除的话,如果后来到来一个查找操作,而此节点位置正好在探测序列上,探测在此处终止而无法对序列后续节点进行探测。