标签:
8. 蛤蟆的数据结构进阶八哈希表相关概念
本篇名言:“作家当然必须挣钱才能生活,写作,但是他决不应该为了挣钱而生活,写作。--马克思”
前些笔记我们学习了二叉树相关。现在我们来看下哈希表。这篇先来看下哈希表的相关概念
欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/47347273
哈希表(HashTable)也叫散列表,是根据关键码值(Key Value)而直接进行访问的数据结构。它通过把关键码值映射到哈希表中的一个位置来访问记录,以加快查找的速度。这个映射函数就做散列函数,存放记录的数组叫做散列表。
以数据中每个元素的关键字K为自变量,通过散列函数H(k)计算出函数值,以该函数值作为一块连续存储空间的的单元地址,将该元素存储到函数值对应的单元中。
哈希表查找的时间复杂度
哈希表存储的是键值对,其查找的时间复杂度与元素数量多少无关,哈希表在查找元素时是通过计算哈希码值来定位元素的位置从而直接访问元素的,因此,哈希表查找的时间复杂度为O(1)。
例,假设有一批关键字序列18,75,60,43,54,90,46,给定哈希函数H(k)=k%13,存贮区的内存地址从0到15,则可以得到每个关键字的散列地址为:
H(18)=18%13=5
H(75)=75%13=10
H(60)=60%13=8
H(43)=43%13=4
H(54)=54%13=2
H(90)=90%13=12
H(46)=46%13=7
上面这个例子讨论的哈希表是一种理想的情形,即每一个关键字对应一个唯一的地址。但是有可能出现这样的情形,两个不同的关键字有可能对应同一个内存地址,即两个记录的关键值不等,但它们的哈希函数的值相同,这样,将导致后放的关键字无法存贮,我们把这种现象叫做冲突(collision)。在散列存贮中,冲突是很难避免的,除非构造出的哈希函数为线性函数。哈希函数选得比较差,则发生冲突的可能性越大。我们把相互发生冲突的关键字互称为“同义词”。
哈希函数的构造目标是使哈希地址尽可能均匀地分布在散列空间上,同时使计算尽可能简单,冲突次数少。具体常用的构造方法有如下几种:
可表示为H(k)=a.k+b,其中a、b均为常数。
这种方法计算特别简单,并且不会发生冲突,但当关键字分布不连续时,会出现很多空闲单元,将造成大量存贮单元的浪费
对关键字序列进行分析,取那些位上数字变化多的、频率大的作为哈希函数地址
取关键字平方后的中间几位为哈希函数地址。这是一种比较常用的哈希函数构造方法,但在选定哈希函数时不一定知道关键字的全部信息,取其中哪几位也不一定合适,而一个数平方后的中间几位数和数的每一位都相关,因此,可以使用随机分布的关键字得到哈希函数地址。
将关键字分割成位数相同的几部分(最后一部分的位数可以不同),然后取这几部分的叠加和(舍去进位)作为哈希函数地址,称为折叠法。
例如,假设关键字为某人身份证号码430104681015355,则可以用4位为一组进行叠加,即有5355+8101+1046+430=14932,舍去高位,则有H(430104681015355)=4932为该身份证关键字的哈希函数地址。
该方法是用关键字序列中的关键字k除以一个整数p所得余数作为哈希函数的地址,即
除留余数法计算简单,适用范围广,是一种最常使用的方法。这种方法的关键是选取较理想的p值,使得每一个关键字通过该函数转换后映射到散列空间上任一地址的概率都相等,从而尽可能减少发生冲突的可能性。一般情形下,p 取为一个素数较理想,并且要求装填因子α最好是在0.6∽0.9之间,所以p 最好取1.1n∽1.7n之间的一个素数较好,其中n为哈希表中待装元素个数。
选择一个随机函数,取关键值的随机函数值为它的哈希地址,即 H(key)=random(key)
random()不能是一般的随机函数,固定的参数必须返回确定的值。
由于哈希存贮中选取的哈希函数不是线性函数,将大的关键值的取值空间映射到小的地址空间中,故不可避免地会产生冲突,下面给出常见的解决冲突方法。
开放定址法就是从发生冲突的那个单元开始,按照一定的次序,从哈希表中找出一个空闲的存储单元,把发生冲突的待插入关键字存储到该单元中,从而解决冲突的发生。在哈希表未满时,处理冲突需要的“下一个”空地址在哈希表中解决。
链地址法也称拉链法,是把相互发生冲突的同义词用一个单链表链接起来,若干组同义词可以组成若干个单链表
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/notbaron/article/details/47347273