1145 Hashing - Average Search Time (25 分) 哈希表 平均查找长度

题干太长了,这次不写题干了,主要说说散列表,又叫哈希表(hash table)

散列表是一种存储数据的方法,通过散列表,可以实现直接用关键字(key)访问数据所在位置。具体实现方法为使用散列函数(哈希函数)H(key),对每个关键字,都可以计算出一个地址。显然,不同的关键字可能有同一个地址,造成地址冲突,有解决这些地址冲突的方法。

H(key)=address

哈希函数有很多种构造方法,常用的有除留余数法等,除留余数法如下,memory_size为分配的存储区域的容量。

H(key%memory_size)=address

其他方法也能将关键字转成对应地址。

如果两个不同键值计算出了相同的地址,就叫做发生了冲突,这些发生碰撞的不同关键字称为同义词,例如除留余数法,若memory_size=5,那么关键字6和11计算出的地址是相同的。

产生冲突,就需要就解决冲突的方法。解决冲突有两大类方法,一是开放定址法,二是链接法。

  • 开放定址法:定义很抽象,大意就是采用某种规则,发生冲突后,重新计算地址进行试探。设第i次冲突时下一个试探地址是Hi,则数学公式是Hi=(H(key)+di)%m。我们的目的是确定重新计算的规则,也就是确定di的取值,来不停地计算试探地址,直到找到不冲突的地址或者超过试探次数限制。常用的开放定址法有常用的开放定址法有平方探测法等。
    平方探测法:di=0,12,-12,22,-22,···,k2,-k2,k<=m/2.依次试探上述取值,直到找到空闲地址或者试探超过m+1次。

本题中就要使用平方探测法。

#include <bits/stdc++.h>
#define N 100000
using namespace std;

bool is_Prime(int n)    {
    if (n==1||n==0) return false;
    for (int i=2;i*i<=n;i++)
        if (n%i==0) return false;
    return true;
}
int ha[N];
int main()  {
    int s,n,m,ans=0;
    scanf("%d%d%d",&s,&n,&m);
    while (!is_Prime(s))    s++;
    for (int i=0;i<n;i++)  {
        int flag=0,t=0;
        scanf("%d",&t);
        for (int j=0;j<=s;j++)  {
            int key=(t+j*j)%s;
            if (ha[key]==0)   {
                ha[key]=t;
                flag=1;
                break;
            }
        }
        if (!flag)  printf("%d cannot be inserted.\n",t);
    }
    for (int i=0;i<m;i++)   {
        int t=0;
        scanf("%d",&t);
        for (int j=0;j<=s;j++)  {
            ans++;
            int tk=(t+j*j)%s;
            if (ha[tk]==t||ha[tk]==0)   break;
        }
    }
    printf("%.1f\n",1.0*ans/m);
    return 0;
}
相关推荐
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页