哈希表

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

通俗的来说,哈希表结构是通过数组+链表来实现的,哈希表的做法其实很简单,就是把key通过一个固定的算法函数即所谓的哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的下标,将value存储在以该数字为下标的数组空间里。而当使用哈希表进行查询的时候,就是再次使用哈希函数将key转换为对应的数组下标,并定位到该空间获取value,如此一来,就可以充分利用到数组的定位性能进行数据定位。另外哈希表中的数组默认长度是16个单位,因子是0.75,也就是说十六个位置如果16*0.75=12个位置有存值,便会重新散列,即打乱重新计算填充。散列会耗费大量性能,所以我们在初始化的时候可以指定初始容量,避免过多的散列。

当然,既然有计算,就不可避免冲突(collision)现象:对不同的关键字可能得到同一哈希地址 即key1≠key2,而hash(key1)=hash(key2)。具有相同函数值的关键字对该哈希函数来说称为同义词(synonym)。因此,在建造哈希表时不仅要设定一个好的哈希函数,而且要设定一种处理冲突的方法。可如下描述哈希表:

根据设定的哈希函数H(key)和所选中的处理冲突的方法,将一组关键字映象到一个有限的、地址连续的地址集(区间)上并以关键字在地址集中的“象”作为相应记录在表中的存储位置,这种表被称为哈希表。处理冲突当然也有考虑到,

所以处理方法有:

  1. 开放定址法

    所谓开放定址法,即是由关键码得到的哈希地址一旦产生了冲突,也就是说,该地址已经存放了数据元素,

  2. 链地址法

    设哈希函数得到的哈希地址域在区间[0,m-1]上,以每个哈希地址作为一个指针,指向一个链,即分配指针数组ElemType*eptr[m];建立m个空链表,由哈希函数对关键码转换后,映射到同一哈希地址i的同义词均加入到*eptr[i]指向的链表中。就去寻找下一个空的哈希地址,只要哈希表足够大,空的哈希地址总能找到,并将数据元素存入。

  3. 建立一个公共溢出区

    设哈希函数产生的哈希地址集为[0,m-1],则分配两个表:
    一个基本表ElemTypebase_tbl[m];每个单元只能存放一个元素;
    一个溢出表ElemTypeover_tbl[k];只要关键码对应的哈希地址在基本表上产生冲突,则所有这样的元素一律存入该表中。查找时,对给定值kx通过哈希函数计算出哈希地址i,先与基本表的base_tbl[i]单元比较,若相等,查找成功;否则,再到溢出表中进行查找。

哈希表的查找分析

哈希表的查找过程基本上和造表过程相同。一些关键码可通过哈希函数转换的地址直接找到,另一些关键码在哈希函数得到的地址上产生了冲突,需要按处理冲 突的方法进行查找。在介绍的三种处理冲突的方法中,产生冲突后的查找仍然是给定值与关键码进行比较的过程。所以,对哈希表查找效率的量度,依然用平均查找 长度来衡量。

查找过程中,关键码的比较次数,取决于产生冲突的多少,产生的冲突少,查找效率就高,产生的冲突多,查找效率就低。因此,影响产生冲突多少的因素,也就是影响查找效率的因素。影响产生冲突多少有以下三个因素:
1. 哈希函数是否均匀; 
2. 处理冲突的方法; 
3. 哈希表的装填因子。
  
分析这三个因素,尽管哈希函数的“好坏”直接影响冲突产生的频度,但一般情况下,我们总认为所选的哈希函数是“均匀的”,因此,可不考虑哈希函数对平 均查找长度的影响。就线性探测法和二次探测法处理冲突的例子看,相同的关键码集合、同样的哈希函数,但在数据元素查找等概率情况下,它们的平均查找长度却 不同:
线性探测法的平均查找长度ASL=(5×1+3×2+1×4)/9=5/3
二次探测法的平均查找长度ASL=(5×1+3×2+1×2)/9=13/9
填入表中的元素个数
哈希表的装填因子定义为:α=────────────

哈希表的长度 

α是哈希表装满程度的标志因子。由于表长是定值,α与“填入表中的元素个数”成正比,所以,α越大,填入表中的元素较多,产生冲突的可能性就越大;α越小,填入表中的元素较少,产生冲突的可能性就越小。

实际上,哈希表的平均查找长度是装填因子α的函数,只是不同处理冲突的方法有不同的函数。以下给出几种不同处理冲突方法的平均查找长度:
这里写图片描述

哈希方法存取速度快,也较节省空间,静态查找、动态查找均适用,但由于存取是随机的,因此,不便于顺序查找。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值