查找-哈希查找

版权声明:转载请注明出处。 https://blog.csdn.net/baidu_38304645/article/details/83089160

在前面讨论的各种结构(线性表、树等)中,记录在结构中的相对位置是随机的,和记录的关键字之后不存在确定的关系。因此,在结构中查找记录时需进行一系列和关键字的比较。这一类查找方法建立在比较的基础上。

理想的情况是希望不经过任何比较,一次存取就能得到所查记录。如何得到?

根据所查找的关键字计算元素位置,设法使得记录在表中的位置和它的关键字取值联系起来。

冲突:不同的关键字可能得到同一个哈希地址的现象,若可能出现冲突则应制定相应的冲突处理方法。如将同余的记录组成一个链表。

根据设定的哈希函数和处理冲突的方法,将一组关键字映像到一组有限连续的存储空间上,以关键字对应的Hash函数值作存储地址。如此所得表为哈希表。

映像过程称为哈希造表或散列。存储地址称为哈希地址或散列地址。

关键是构造合适的Hash函数和找合适的冲突处理方法。而好的Hash函数应该使冲突尽量少。

下面看一个实例:

使用Hash函数,实现对字符串S的哈希值的计算,n为字符串长度。哈希值计算过程中要注意取模,防止溢出。输入必须保证冲突处理所取的步长小于(1 << 31)。用二次探测再散列的方法处理冲突.

H(key) = (s[0] * 31^(n – 1) + s[1] * 31 ^ (n – 2) + ….. + s[n – 1] * 31 ^ 0) % mod;

可能用到的两个取模公式:

扫描二维码关注公众号,回复: 3610164 查看本文章

(a + b) % mod = (a % mod + b % mod) % mod

 (a – b) % mod = (a % mod – b % mod + mod) % mod

输入:字符串的数目N,余数mod,各个字符串。

输出:对于各个字符串,输出计算得到的Hash地址。

运行结果:

具体思想:

按照公式计算,计算的时候小心溢出就可以了。

处理冲突:

开放定址法:处理冲突时加一个增量di。

H0 = H(key)。

Hi = (H0 + di) % m

直到Hs处无冲突。其中m为表长。

其中增量di的取值方法:二次探测再散列。

di=1,-1,4,-4,9, -9, 16, -16…

具体实现:

辅助宏:

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW -1
#define NULL 0
typedef int *SSTable;
typedef char* KeyType;
typedef int Status;

返回关键字key的哈希地址

int Hash(KeyType key,int mod,SSTable ST)
{
    //返回关键字key的哈希地址
   int i,l,j;
   unsigned long long sum,hash=0;
   l=strlen(key);
   for(i=0;i<l;i++)  //计算哈希地址
   {
      sum=1;
      for(j=0;j<l-1-i;j++)
         sum=(sum*(31%mod))%mod; //注意每次计算都要取余防止溢出
      sum=(sum*(key[i]%mod))%mod;
      hash=(hash+sum)%mod;
   }
   hash=hash%mod;
   if(!ST[hash])
   {
      ST[hash]=TRUE;
      return hash;
   }
   else //处理冲突
   {
      int i=1;
      unsigned long long temp;
      while(1)
      {
         temp=hash;
         temp=( temp%mod+( (i%mod)*(i%mod) )%mod )%mod;
         if(!ST[temp])
         {
            ST[temp]=TRUE;
            break;
         }
         temp=hash;
         temp=(temp%mod-((i%mod)*(i%mod))%mod+mod)%mod;
         if(!ST[temp])
         {
            ST[temp]=TRUE;
            break;
         }
         i++;
      }
      return temp;
   }
}

哈希表查找的性能分析:

虽然哈希函数确定了关键字及其存储位置之间的映像,但由于冲突的存在,Hash表的查找仍然要进行比较,平均查找长度也并非一定为零。

决定哈希表查找的ASL的因素,哈希函数,处理冲突方法以及哈希表的装填因子(饱和度)a=n/m  n-记录数 m-表的长度。

通常假定哈希函数均匀。从而忽略其对ASL的影响。平均情况下,不同的冲突处理办法下ASL是装填因子的一个函数。而不是n的函数。不管n多大,总可选择合适的装填因子时ASL限定在一个范围内。

猜你喜欢

转载自blog.csdn.net/baidu_38304645/article/details/83089160