题目链接在此。
题意
给出表长m和要插入的元素个数n,以及n个要插入的元素,讲这些元素按照顺序插入散列表中,其中散列函数为H(key) = key%m,解决冲突的策略采用正想增加的二次探测法。
若给出的表长m不是素数,则将m重新复制为第一个比m大的素数作为表长。
什么是二次方探测法:
首先需要了解什么是二次方探测法。
这时一种在填充散列表示解决冲突的一种办法,举给例子来说明:比如key通过散列函数后得到的位置上已经存在元素,那么下一个就看(key+1*1)%m,若这一位上依旧有元素,探测(key-1*1),依次类推:(key+2*2), (key-2*2), (key+3*3), (key+4*4)…..一直到(key-(m-1)*(m-1))(为什么到m-1呢?因为循环节是m-1,具体证明略)。
AC代码
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn = 11111;
int m,n;
int a[maxn];
bool hashTable[maxn] = {0};
//判断一个数是不是素数
bool isPrime(int x){
if(x <= 1) return false;
int sqr = (int)sqrt(x*1.0);
for(int i = 2; i <= sqr; i++){
if(x%i == 0) return false;
}
return true;
}
int main(){
scanf("%d %d",&m,&n);
while(isPrime(m) == false){ //找到第一个比m大的素数
m++;
}
for(int i = 0; i < n; i++){
scanf("%d",&a[i]);
int pos = a[i]%m; //根据hash公式得到的位置
if(hashTable[pos] == false){ //如果pos位置可以放置
hashTable[pos] = true; //则放到pos位置,置pos为true
if(i == 0){ //控制输出格式
printf("%d",pos);
} else{
printf(" %d",pos);
}
} else{ //如果pos位置已经有元素
int step;
for(step = 1; step < m; step++){ //进行平方探测
pos = (a[i]+step*step)%m; //放置位置
if(hashTable[pos] == false){
hashTable[pos] = true;
if(i == 0){ //控制输出格式
printf("%d",pos);
}else{
printf(" %d",pos);
}
break;
}
}
if(step >= m){ //找不到合理的位置
if(i > 0) printf(" "); //控制输出格式
printf("-");
}
}
}
return 0;
}