晴神宝典上的写法
# include <iostream>
# include <cmath>
# include <vector>
# include <algorithm>
# include <climits>
using namespace std;
bool isPrime(int n)
{
if(n == 1)
return false;
int sq = (int)sqrt(n);
for(int i=2;i<=sq;++i)
if(n%i == 0)
return false;
return true;
}
int main(void)
{
int Tsize, N, val;
int HASH[10010] = {
0};
cin >> Tsize >> N;
while(!isPrime(Tsize))
Tsize++;
for(int i=0;i<N;++i){
cin >> val; // 要存入哈希表的数据
int key = val % Tsize; // 数据在哈希表中的初始键
// 如果初始键的位置未使用
if(HASH[key] == 0){
HASH[key] = val;
cout << key;
if(i != N-1) cout << " ";
}
// 如果初始键的位置被使用,就使用二次探测法,一直探测步长1 ~ Tsize-1的范围
else{
int step; // 二次探测法的步长
for(step = 1;step<Tsize;++step){
key = (val + step*step) % Tsize; // 二次探测法的冲突处理公式
if(HASH[key] == 0){
HASH[key] = val;
cout << key;
if(i != N-1) cout << " ";
break;
}
}
// 如果探测找不到位置,说明该数据无法存储在当前哈希表
if(step >= Tsize){
cout << "-";
if(i != N-1) cout << " ";
}
}
}
return 0;
}
因为初始键其实就是步长为0的时候,所以我稍微改进了一下,代码精简了一些
# include <iostream>
# include <cmath>
# include <vector>
# include <algorithm>
# include <climits>
using namespace std;
bool isPrime(int n)
{
if(n == 1)
return false;
int sq = (int)sqrt(n);
for(int i=2;i<=sq;++i)
if(n%i == 0)
return false;
return true;
}
int main(void)
{
int Tsize, N, val, step, key;
int HASH[10010] = {
0};
cin >> Tsize >> N;
// TSize不是素数就让他成为比它更大的素数
while(!isPrime(Tsize))
Tsize++;
for(int i=0;i<N;++i)
{
cin >> val; // 要存入哈希表的数据
// 使用二次探测法探测当前数据的映射存储位置
// 初始键就是步长step为0,所以放在一个for循环处理也没问题
for(step = 0;step<Tsize;++step){
key = (val + step*step) % Tsize; // 二次探测法的冲突处理公式
if(HASH[key] == 0){
// 如果当前位置未使用,就存入
HASH[key] = val;
cout << key;
if(i != N-1) cout << " ";
break; // 记得break
}
}
if(step >= Tsize){
// 如果探测找不到位置,说明该数据无法存储在当前哈希表
cout << "-";
if(i != N-1) cout << " ";
}
}
return 0;
}