[数据结构] Hash表、Hash函数及冲突解决

1.Hash表

  哈希表(Hash table,也叫散列表),是根据key而直接进行访问的数据结构。也就是说,它通过把key映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

  以数据中每个元素的关键字K为自变量,通过散列函数H(k)计算出函数值,以该函数值作为一块连续存储空间的的单元地址,将该元素存储到函数值对应的单元中。

  哈希表存储的是键值对,其查找的时间复杂度与元素数量多少无关,哈希表在查找元素时是通过计算哈希码值来定位元素的位置从而直接访问元素的,因此,哈希表查找的时间复杂度为O(1)。

2.哈希表的构造方法

2.1直接定址法

  取关键字或者关键字的某个线性函数值作为哈希地址,即 

  

  H(Key)=Key或者H(Key)=a*Key+b(a,b为整数) 

  

  这种散列函数也叫做自身函数.如果H(Key)的哈希地址上已经有值了,那么就往下一个位置找,直到找到H(Key)的位置没有值了就把元素放进去. 

  此法仅适合于:地址集合的大小 等于 关键字集合的大小

2.2 数字分析法

  分析一组数据,比如一组员工的出生年月,这时我们发现出生年月的前几位数字一般都相同,因此,出现冲突的概率就会很大,但是我们发现年月日的后几位表示月份和具体日期的数字差别很大,如果利用后面的几位数字来构造散列地址,则冲突的几率则会明显降低.

  因此数字分析法就是找出数字的规律,尽可能利用这些数据来构造冲突几率较低的散列地址.  

  此法适于:能预先估计出全体关键字的每一位上各种数字出现的频度。

2.3 平方取中法 

  以关键字的平方值的中间几位作为存储地址(哈希地址)。求“关键字的平方值” 的目的是“扩大差别” ,同时平方值的中间各位又能受到整个关键字中各位的影响。 

  此法适于:关键字中的每一位都有某些数字重复出现频度很高的现象。

2.4 折叠法 

   将关键字分割成若干部分,然后取它们的叠加和为哈希地址。两种叠加处理的方法:移位叠加:将分 割后的几部分低位对齐相加;间界叠加:从一端沿分割界来回折叠,然后对齐相加。

  

  此法适于:关键字的数字位数特别多。 

2.5随机数法

  设定哈希函数为:H(key) = Random(key)其中,Random 为伪随机函数

此法适于:对长度不等的关键字构造哈希函数。

2.6除留余数法

  取关键字被某个不大于散列表表长m的数p除后所得的余数为散列地址.即

  哈希函数为:H(key) = key MOD p ( p≤m ),其中, m为表长,p 为不大于 m 的素数。

3.哈希表冲突解决方法

  哈希表处理冲突主要有开放寻址法再散列法链地址法(拉链法)和建立一个公共溢出区四种方法。

  通过构造性能良好的哈希函数,可以减少冲突,但一般不可能完全避免冲突,因此解决冲突是哈希法的另一个关键问题。

 “处理冲突” 的实际含义是:为产生冲突的关键字寻找下一个哈希地址。

3.1开放定址法

  

  一旦发生了冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入。

3.1.1线性探测

  冲突发生时,顺序查看表中下一单元,直到找出一个空单元或查遍全表。

  公式:

  

fi(key) = (f(key)+di) MOD m (di=1,2,3,......,m-1)

3.1.2二次探测法

  冲突发生时,在表的左右进行跳跃式探测,双向寻找到可能的空位置。

公式:

fi(key) = (f(key)+di) MOD m (di = 12, -12, 22, -22,……, q2, -q2, q <= m/2)

3.1.3随机探测法

  在冲突时,对于位移量 di 采用随机函数计算得到,我们称之为随机探测法。

 公式:

 

fi(key) = (f(key)+di) MOD m (di是一个随机数列)

  线性探测再散列容易产生“二次聚集”,即在处理同义词的冲突时又导致非同义词的冲突。

  线性探测再散列的优点是:只要哈希表不满,就一定能找到一个不冲突的哈希地址,而二次探测再散列和伪随机探测再散列则不一定。

3.2链地址法

   将所有哈希地址相同的记录都链接在同一链表中。各链表上的结点空间是动态申请的,故它更适合于造表前无法确定表长的情况。

   处理冲突简单,且无堆积现象,即非同义词决不会发生冲突,因此平均查找长度较短;

3.3再哈希法

这种方法是同时构造多个不同的哈希函数:

Hi=RH1(key),i=1,2,3,…,n.

当哈希地址Hi=RH1(key)发生冲突时,再计算Hi=RH2(key)……,直到冲突不再产生。这种方法不易产生聚集,但增加了计算时间。

3.4建立公共溢出区

  这种方法的基本思想是:将哈希表分为基本表和溢出表两部分,凡是和基本表发生冲突的元素,一律填入溢出表.(注意:在这个方法里面是把元素分开两个表来存储)

时间: 2024-10-07 13:41:44

[数据结构] Hash表、Hash函数及冲突解决的相关文章

Hash表的hash函数,冲突解决方法有哪些

最常用的3个HASH函数: 1. 除法散列法:通过取k除以m的余数,来将关键字k映射到m个槽的某一个中去,即散列函数为: h(k) = k mod m 2. 乘法散列法:首先,用关键字k乘上常数A(0<A<1),并抽取kA的小数部分:然后,用m乘以这个值,再取结果的底(即整数部分).散列函数可表达为: h(k) = ⌊m(kA mod 1)⌋ 3.全域散列法(universal hashing) 解决冲突常用的两种方法: 1. 链接法(chaining):把散列到同一槽中的所有元素都存放在一个

数据结构与算法-hash表

前言 哈希表是一种存放键-值对的数据结构,其中值用来存放我们真正需要的数据,键的主要目的就是为了找到值.哈希表理想情况下,只需要一次hash计算即可找到值数据,但通常情况下我们不需要耗费巨大的额外空间来追求这丝毫的查找速度(要追求低hash冲突率,必然要扩大hash表),我们更希望的是让空间和时间达到某种平衡,这可以通过调节hash函数来解决(装填因子). 装填因子=表中的记录数/哈希表的长度,如果装填因子越小,表明表中还有很多的空单元,则发生冲突的可能性越小:而装填因子越大,则发生冲突的可能性

PHP核心技术与最佳实践之Hash表冲突

PHP核心技术与最佳实践之Hash表冲突 接着上一篇文章,测试后输出value1value2.当 $ht->insert('key12','value12'); Echo $ht ->find('key12');时, 发现输出value12value12.这是什么原因呢? 这个问题称为Hash表的冲突.由于insert的是字符串,采用的算法是将字符串的ASIIC码相加,按照此方法,冲突产生了.通过打印key12和key1的Hash值,发现他们都为8,也就说,value1和value12同时被存

01-(2)数据结构- 一步一步写算法(之hash表)

hash表,有时候也被称为散列表.个人认为,hash表是介于链表和二叉树之间的一种中间结构.链表使用十分方便,但是数据查找十分麻烦:二叉树中的数据严格有序,但是这是以多一个指针作为代价的结果.hash表既满足了数据的查找方便,同时不占用太多的内容空间,使用也十分方便. 打个比方来说,所有的数据就好像许许多多的书本.如果这些书本是一本一本堆起来的,就好像链表或者线性表一样,整个数据会显得非常的无序和凌乱,在你找到自己需要的书之前,你要经历许多的查询过程:而如果你对所有的书本进行编号,并且把这些书本

hash表总结

Hash表也称散列表,也有直接译作哈希表,Hash表是一种特殊的数据结构,它同数组.链表以及二叉排序树等相比较有很明显的区别,它能够快速定位到想要查找的记录,而不是与表中存在的记录的关键字进行比较来进行查找.这个源于Hash表设计的特殊性,它采用了函数映射的思想将记录的存储位置与记录的关键字关联起来,从而能够很快速地进行查找. 1.Hash表的设计思想 对于一般的线性表,比如链表,如果要存储联系人信息: 张三 13980593357 李四 15828662334 王五 13409821234 张

海量路由表可以使用HASH表存储吗-HASH查找和TRIE树查找

千万别!很多人这样说,也包括我.Linux内核早就把HASH路由表去掉了,现在就只剩下TRIE了,不过我还是希望就这两种数据结构展开一些形而上的讨论. 1.hash和trie/radix hash 和tire其实是可以统一在一起的.具有相同hash值的多个项具有一个共同的特征,这个特征怎么提取呢?无疑这就是hash函数的工作.而trie树 (或者radix树,管它呢)的一棵子树也有共同的特征,这个特征怎么提取呢?无疑这就是该子树根节点的父节点指示的某些bits在这棵子树的每一个节点 都具有相同的

hash表简单实现

查找算法大总结: http://www.cnblogs.com/maybe2030/p/4715035.html#_label6 常用的hash函数: http://blog.csdn.net/mycomputerxiaomei/article/details/7641221 什么是哈希表(Hash)? 我们使用一个下标范围比较大的数组来存储元素.可以设计一个函数(哈希函数, 也叫做散列函数),使得每个元素的关键字都与一个函数值(即数组下标)相对应,于是用这个数组单元来存储这个元素:也可以简单的

深入了解STL中set与hash_set,hash表基础

一,set和hash_set简介 在STL中,set是以红黑树(RB-Tree)作为底层数据结构的,hash_set是以哈希表(Hash table)作为底层数据结构的.set可以在时间复杂度为O(logN)的情况下插入,删除和查找数据.hash_set操作的时间度则比较复杂,取决于哈希函数和哈希表的负载情况. 二,SET使用范例(hash_set类似) 1 #include <set> 2 #include <ctime> 3 #include <cstdio> 4

十一、从头到尾彻底解析Hash 表算法

在研究MonetDB时深入的学习了hash算法,看了作者的文章很有感触,所以转发,希望能够使更多人受益! 十一.从头到尾彻底解析Hash 表算法 作者:July.wuliming.pkuoliver  出处:http://blog.csdn.net/v_JULY_v.  说明:本文分为三部分内容,    第一部分为一道百度面试题Top K算法的详解:第二部分为关于Hash表算法的详细阐述:第三部分为打造一个最快的Hash表算法.----------------------------------