哈希表入门

来源:互联网 发布:中信建投股票交易软件 编辑:程序博客网 时间:2024/05/18 00:32

1、哈希表简介


  出现原因:原先的链表、树等查找方式,都需要一个一个的去比较才能找到,查找效率并不高,哈希表的提出就是解决这一问题,哈希表根据要查找的内容进行计算,得出数据的存储地址进而直接访问,大大提高了查找效率。这个运算的过程归纳成一个函数,就是哈希函数。

  在有大量的数据的时候,哈希表比普通的顺序查找要快的多。例如查找某人的身份证,普通方式需要比对很多次,直到比对成功,而哈希表是直接得到身份证号,从而查找到身份证,一步到位。

  哈希表(Hash table),又称散列表或杂凑表,是根据关键码值(Key value)而直接进行访问的数据结构,具有极高的查找效率。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。


2、哈希冲突


  哈希冲突是指利用同样的计算方式,对不同的内容计算出相同的哈希地址,这就是哈希冲突,例如:


        


  哈希表需要把巨大的数字空间压缩为较小的数字空间,必然要付出代价,即不能保证每个单词都映射到数组的空白单元。例如上面的哈希函数对21和30求出的哈希地址就是相同的,这就是哈希冲突。


3、哈希函数的构造方法


  对于hash函数的构造没有特定要求,只要能够最大可能的避免哈希冲突,就是好的哈希函数。一般有以下几种构造方法:


  (1)直接定址法


    取关键字或关键字的某个线性函数值为散列地址。即H(key)=key或H(key) = a•key + b,其中a和b为常数(这种散列函数叫做自身函数)。


  (2)除余法


    以关键码除以表元素总数后得到的余数为存储地址。除余法很好理解,上例中k MOD 3就是除余法的应用。


  (3)基数转换法


    将关键码看作是某个基数制上的整数,然后将其转换为另一基数制上的数。如下:


              


  (4)平方取中法


    求得关键字的平方,然后根据表长度取中间的几位数作为散列函数值。又因为一个乘积的中间几位数和乘数的的每一位都相关,所以由此产生的散列地址较为均匀。例如:


          


  (5)折叠法


    折叠法即将关键字分割成位数相同的几部分,最后一部分位数可以不同,然后取这几部分的叠加和(注意:叠加和时去除进位)作为散列地址。数位叠加可以有移位叠加和间界叠加两种方法。移位叠加是将分割后的每一部分的最低位对齐,然后相加;间界叠加是从一端向另一端沿分割界来回折叠,然后对齐相加。


4、哈希冲突的处理


  哈希冲突是必须处理的,一般处理方式有:


  (1)开放定址法


    当冲突发生时,使用某种探查技术在散列中形成一个探序列。沿着该序列查找,直到找到关键字或一个开放的地址(即地址单元为空)。一般有线性探查法和双散列函数法:


    ● 线性探查法


      发生冲突后直接向下线性找一个新的空间存放。例如:


         


      3和8的哈希地址都为3号地址,当存储8的时候发现地址内已经存储了3,那么就向下探查到4号地址,如果为空,就将8存储到4号地址,依次类推,发生冲突就向下探查,知道发现开放地址。

    同时还有二次探查法,即向下探测的间隔是平方式,例如哈希表中原始下标是x,那么线性探测是:x+1,x+2,x+3……;而在二次探测中,探测过程是:x+12,x+22,x+32……。二次探测是防止聚集的产生,思想是探测相隔较远的单元,而不是相邻的单元。


    ● 双散列函数法


      双散列函数法也很简单,例如:


        


      当发生冲突之后,向下探查的间隔由函数hi决定。


  (2)拉链法


    当存储结构是链表时,多采用拉链法,用拉链法处理冲突的办法是:把具有相同散列地址的关键字(同义词)值放在同一个单链表中,称为同义词链表。有m个散列地址就有m个链表,同时用指针数组T[0..m-1]存放各个链表的头指针,凡是散列地址为i的记录都以结点方式插入到以T[i]为指针的单链表中。T中各分量的初值应为空指针。


      


    用拉链法处理冲突,虽然比开放定址法多占用一些存储空间用做链接指针,但它可以减少在插入和查找过程中同关键字平均比较次数(平均查找长度),这是因为,在拉链法中待比较的结点都是同义词结点,而在开放定址法中,待比较的结点不仅包含有同义词结点,而且包含有非同义词结点,往往非同义词结点比同义词结点还要多。

    显然,开放定址法处理冲突的的平均查找长度要高于拉链法处理冲突的平均查找长度。

    拉链法的缺点:指针需要额外的空间,故当结点规模较小时,开放定址法较为节省空间,而若将节省的指针空间用来扩大散列表的规模,可使装填因子变小,这又减少了开放定址法中的冲突,从而提高平均查找速度。


  (3)建立公共溢出区


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


5、处理方式的选用


  (1)当有大量冲突需要解决


    当冲突太多的时候,我们一般采用的方法时拉链法,采用拉链法的原因是动态申请空间,将H(key)相同的关键字都统一放到一个链里,当出现冲突的时候我们就把该元素接在链表后面,这样可以避免产生堆积现象,缩短平均查找长度。


  (2)数据表太小,数据太多


    当数据表太小数据太多可以通过建立一个溢出表,专门用来存放溢出记录。




4 0
原创粉丝点击