看了网上太多的答案,大多也是柳神那个版本出来的;讲真那个版本真的适合初学者吗?
或许考试这么写没问题,但是丧失了可读性,个人觉得并不是什么“好代码”
分析
即代码模拟 二次冲突下的散列
- 插入:
位置=值%表长+i^2
此时位置需落在【0,表长-1】,且插入位置有空间插入
- 搜索
搜索时仍需按照二次冲突的方式来遍历
直到 比较到 相同值,跳出 ;或者达到循环上限跳出
注:题目是Average Search Time是比较次数,与asl还是不一样的
具体实现
由于插入和搜索都需要二次冲突来遍历,因此可以写在同一个模块内;
通过不同的标志搜集所需的内容即可
注意事项
- 表长需修改为 大于原表长的最小素数
- 冲突为正增量:
- 循环范围为:
二次冲突的范围为:【1,表长】
而第一次 =0 不叫冲突,因此 循环从【0,表长】
代码
#include<bits/stdc++.h>
using namespace std;
int m_size, n_insert, n_search, sum{ 0 };
vector<int>table;
bool IsPrime(int);
void InPut();
int Probing(int);
void Insert();
void Search();
int main() {
InPut();
Insert();
Search();
return 0;
}
bool IsPrime(int x) {
for (int i = 2; i * i <= x; i++) {
if (x % i == 0)
return false;
}
return true;
}
void InPut() {
scanf("%d %d %d", &m_size, &n_insert, &n_search);
while (!IsPrime(m_size))
m_size++;
table.resize(m_size);
fill(table.begin(), table.end(), 0);
}
int Probing(int x) {
int a;
for (int i = 0; i <= m_size; i++) {
sum++;
a = x % m_size + i * i;
while (a > m_size - 1)
a = a % m_size;
if (table[a] == 0)
return a;
if (table[a] == x)
return a;
}
return -1;
}
void Insert() {
int x, y;
for (int i = 0; i < n_insert; i++) {
scanf("%d", &x);
y = Probing(x);
y != -1 ? table[y] = x : printf("%d cannot be inserted.\n", x);
}
}
void Search() {
int x, y;
sum = 0;
for (int i = 0; i < n_search; i++) {
scanf("%d", &x);
y = Probing(x);
}
printf("%.1f\n", sum * 1.0 / n_search);
}