#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int maxn = 100;
int n;//记录个数
int n1, n2; //n1,n2分别表示两个散列表里面的用户数
int m;//散列表大小
//用户信息
struct record {
char telnum[maxn]; //电话号码
char telname[maxn]; //用户名
char teladd[maxn]; //地址
bool flag; //标志位,如果flag=false,说明此处无数据。反之,则有数据
int count = 0; //记录发生冲突的次数
};
struct record rec1[maxn]; //电话号码散列表
struct record rec2[maxn]; //用户名散列表
//判断素数
bool isprime(int n) {
if (n <= 1) return false;
long long m = floor(sqrt(n) + 0.5);
for (long long i = 2; i <= m; ++i) {
if (n%i == 0) return false;
}
return true;
}
//确定除留取余法的除数
int confirm(int m) {
while (!isprime(m)) { //如果函数返回值是false,说明m不是素数,就把m--
--m;
}
return m;
}
//构建电话号码散列表
void init1() {
while (n1--) {
char telnum[maxn], telname[maxn], teladd[maxn];
cout << "请输入电话号码:";
cin >> telnum;
cout << "请输入用户名:";
cin >> telname;
cout << "请输入地址:";
cin >> teladd;
int sum(0);
bool flag = false;
int count(0); //记录发生冲突的次数
for (int i = 0; i <strlen(telnum); ++i) {
sum += telnum[i] - '0'; //计算key值
}
sum = sum % m; //除留取余,找到key值在散列表中对应的位置
while (rec1[sum].flag == true) { //如果该位置已经有数据了,就向后移动一位
if (sum < m - 1) sum++; //如果已经移动到最后一位了,就
else sum = 0; //从头开始判断
++count; //记录冲突次数
if (count == m) {
cout << telnum << "插入不进散列表" << endl;
break;
}
}
if (count != m) {
strcpy(rec1[sum].telnum, telnum);
strcpy(rec1[sum].telname, telname);
strcpy(rec1[sum].teladd, teladd);
rec1[sum].flag = true;
rec1[sum].count = count;
}
}
}
//通过电话号码查询信息
void print1() {
char t[20];
cout << "请输入需要查找的电话号码:";
cin >> t;
int sum(0);
for (int i = 0; i <strlen(t); ++i) {
sum += t[i] - '0'; //计算key值
}
sum = sum % m; //除留取余,找到key值在散列表中对应的位置
int count(0); //记录判断的次数
while (strcmp(rec1[sum].telnum, t) != 0) {
if (sum < m - 1) sum++; //如果已经移动到最后一位了,就
else sum = 0; //从头开始判断
++count; //记录冲突次数
if (count == m) {
cout << "查询失败" << endl;
cout << t << "不在散列表中" << endl;
break;
}
}
if (count != m) {
cout << "查询成功" << endl;
cout << "电话号码:" << rec1[sum].telnum << endl;
cout << "用户名:" << rec1[sum].telname << endl;
cout << "地址:" << rec1[sum].teladd << endl;
cout << "冲突次数:" << rec1[sum].count << endl;
}
}
//根据电话号码插入用户
void insert1() {
char telnum[maxn], telname[maxn], teladd[maxn];
cout << "请输入需要插入的用户的电话号码 ";
cin >> telnum;
ll sum(0);
bool flag = false;
int count(0); //记录发生冲突的次数
for (int i = 0; i <strlen(telnum); ++i) {
sum += telnum[i] - '0'; //计算key值
}
sum = sum % m; //除留取余,找到key值在散列表中对应的位置
while (rec1[sum].flag == true) { //如果该位置已经有数据了,就向后移动一位
if (sum < m - 1) sum++; //如果已经移动到最后一位了,就
else sum = 0; //从头开始判断
++count; //记录冲突次数
if (count == m) {
cout << "通讯录已满,用户电话号码为" << telnum << "的用户插入失败" << endl;
break;
}
}
if (count != m) {
cout << "插入成功,请完善该用户的其他信息" << endl;
cout << "请输入用户名:";
cin >> telname;
cout << "请输入地址:";
cin >> teladd;
strcpy(rec1[sum].telnum, telnum);
strcpy(rec1[sum].telname, telname);
strcpy(rec1[sum].teladd, teladd);
rec1[sum].flag = true;
rec1[sum].count = count;
}
}
//根据电话号码删除用户
void Delete1() {
char telnum[maxn], telname[maxn], teladd[maxn];
cout << "请输入需要删除的用户的电话号码 ";
cin >> telnum;
int sum(0);
bool flag = false;
int count(0); //记录发生冲突的次数
for (int i = 0; i <strlen(telnum); ++i) {
sum += telnum[i] - '0'; //计算key值
}
sum = sum % m; //除留取余,找到key值在散列表中对应的位置
while (strcmp(rec1[sum].telnum, telnum) != 0||rec1[sum].flag==false) {
if (sum < m - 1) sum++; //如果已经移动到最后一位了,就
else sum = 0; //从头开始判断
++count; //记录冲突次数
if (count == m) {
cout << "删除失败,电话号码为" << telnum << "的用户不在通讯录中" << endl;
break;
}
}
if (count != m) {
cout << "删除成功" << endl;
rec1[sum].flag = false;
}
}
//显示电话号码散列表的信息
void fun1() {
cout << "******************************" << endl;
cout << "********电话号码通讯录********" << endl;
cout << "******************************" << endl;
for (int i = 0; i < m; ++i) {
if (rec1[i].flag == true) {
cout << i << "号用户的信息" << "电话号码:" << rec1[i].telnum << " " << "用户名:" << rec1[i].telname << " " << "地址:" << rec1[i].teladd << " " << "冲突次数:" << rec1[i].count << endl;
}
}
}
//计算电话号码通讯录查找成功的ASL
void succ_asl1() {
int counter = 0; //统计发生冲突的次数
int counter1 = 0; //统计散列表里面有多少个数据
for (int i = 0; i < m; ++i) {
if (rec1[i].flag) {
counter += rec1[i].count+1;
++counter1;
}
}
double succ_asl;
if (counter1 != 0) {
succ_asl = (double)((double)counter / (double)counter1);
}
cout << counter << endl;
cout<<"查找成功的ASL为 "<< setprecision(5) << fixed <<succ_asl<< endl;
}
//计算电话号码通讯录查找失败的ASL
void fail_asl1() {
int counter = 0; //统计发生冲突的次数
int counter1; //统计连续有数据的个数
for (int i = 0; i < m; ++i) {
counter1 = 0;
int temp = i;
while(rec1[temp].flag) {
if (temp == m) {
temp = 0;
}
++counter1;
++temp;
}
counter1++;
counter += counter1;
}
double fail_asl;
fail_asl = (double)((double)counter / (double)m);
cout << counter << endl;
cout << "查找失败的ASL为 " << setprecision(5) << fixed << fail_asl << endl;
cout << counter << endl;
}
//构建用户名散列表
void init2() {
while (n2--) {
char telnum[maxn], telname[maxn], teladd[maxn];
cout << "请输入用户名(请输入英文名):";
cin >> telname;
cout << "请输入电话号码:";
cin >> telnum;
cout << "请输入地址:";
cin >> teladd;
int sum(0);
bool flag = false;
int count(0); //记录发生冲突的次数
for (int i = 0; i <strlen(telname); ++i) {
sum += telname[i] - 'A'; //计算key值
}
sum = sum % m; //除留取余,找到key值在散列表中对应的位置
while (rec2[sum].flag == true) { //如果该位置已经有数据了,就向后移动一位
if (sum < m - 1) sum++; //如果已经移动到最后一位了,就
else sum = 0; //从头开始判断
++count; //记录冲突次数
if (count == m) {
cout << telnum << "插入不进散列表" << endl;
break;
}
}
if (count != m) {
strcpy(rec2[sum].telnum, telnum);
strcpy(rec2[sum].telname, telname);
strcpy(rec2[sum].teladd, teladd);
rec2[sum].flag = true;
rec2[sum].count = count;
}
}
}
//通过用户名查询信息
void print2() {
char t[20];
cout << "请输入需要查找的用户名(请输入英文名):";
cin >> t;
int sum(0);
for (int i = 0; i <strlen(t); ++i) {
sum += t[i] - 'A'; //计算key值
}
sum = sum % m; //除留取余,找到key值在散列表中对应的位置
int count(0); //记录判断的次数
while (strcmp(rec2[sum].telname, t) != 0) {
if (sum < m - 1) sum++; //如果已经移动到最后一位了,就
else sum = 0; //从头开始判断
++count; //记录冲突次数
if (count == m) {
cout << "查询失败" << endl;
cout << t << "不在用户名通讯录中" << endl;
break;
}
}
if (count != m) {
cout << "查询成功" << endl;
cout << "用户名:" << rec2[sum].telname << endl;
cout << "电话号码:" << rec2[sum].telnum << endl;
cout << "地址:" << rec2[sum].teladd << endl;
cout << "冲突次数:" << rec2[sum].count << endl;
}
}
//根据用户名插入用户
void insert2() {
char telnum[maxn], telname[maxn], teladd[maxn];
cout << "请输入需要插入的用户的用户名 ";
cin >> telname;
int sum(0);
bool flag = false;
int count(0); //记录发生冲突的次数
for (int i = 0; i <strlen(telname); ++i) {
sum += telname[i] - 'A'; //计算key值
}
sum = sum % m; //除留取余,找到key值在散列表中对应的位置
while (rec2[sum].flag == true) { //如果该位置已经有数据了,就向后移动一位
if (sum < m - 1) sum++; //如果已经移动到最后一位了,就
else sum = 0; //从头开始判断
++count; //记录冲突次数
if (count == m) {
cout << "通讯录已满,用户名为" << telname << "的用户插入失败" << endl;
break;
}
}
if (count != m) {
cout << "插入成功,请完善该用户的其他信息" << endl;
cout << "请输入电话号码:";
cin >> telnum;
cout << "请输入地址:";
cin >> teladd;
strcpy(rec2[sum].telnum, telnum);
strcpy(rec2[sum].telname, telname);
strcpy(rec2[sum].teladd, teladd);
rec2[sum].flag = true;
rec2[sum].count = count;
}
}
//根据用户名删除用户
void Delete2() {
char telnum[maxn], telname[maxn], teladd[maxn];
cout << "请输入需要删除的用户的用户名 ";
cin >> telname;
int sum(0);
bool flag = false;
int count(0); //记录发生冲突的次数
for (int i = 0; i <strlen(telname); ++i) {
sum += telname[i] - '0'; //计算key值
}
sum = sum % m; //除留取余,找到key值在散列表中对应的位置
while (strcmp(rec2[sum].telname, telname) != 0||rec2[sum].flag==false) {
if (sum < m - 1) sum++; //如果已经移动到最后一位了,就
else sum = 0; //从头开始判断
++count; //记录冲突次数
if (count == m) {
cout << "删除失败,用户名为" << telname << "的用户不在通讯录中" << endl;
break;
}
}
if (count != m) {
cout << "删除成功" << endl;
rec2[sum].flag = false;
}
}
//显示用户名散列表的信息
void fun2() {
cout << "****************************" << endl;
cout << "********用户名通讯录********" << endl;
cout << "****************************" << endl;
for (int i = 0; i < m; ++i) {
if (rec2[i].flag == true) {
cout << i << "号用户的信息" << "用户名:" << rec2[i].telname << " " << "电话号码:" << rec2[i].telnum << " " << "地址:" << rec2[i].teladd << " " << "冲突次数:" << rec2[i].count << endl;
}
}
}
//计算用户名通讯录查找成功的ASL
void succ_asl2() {
int counter = 0; //统计发生冲突的次数
int counter1 = 0; //统计散列表里面有多少个数据
for (int i = 0; i < m; ++i) {
if (rec2[i].flag) {
counter += rec2[i].count + 1;
++counter1;
}
}
double succ_asl;
if (counter1 != 0) {
succ_asl = (double)((double)counter / (double)counter1);
}
cout << counter << endl;
cout << "查找成功的ASL为 " << setprecision(5) << fixed << succ_asl << endl;
}
//计算用户名通讯录查找失败的ASL
void fail_asl2() {
int counter = 0; //统计发生冲突的次数
int counter1; //统计连续有数据的个数
for (int i = 0; i < m; ++i) {
counter1 = 0;
int temp = i;
while (rec2[temp].flag) {
if (temp == m) {
temp = 0;
}
++counter1;
++temp;
}
counter1++;
counter += counter1;
}
double fail_asl;
fail_asl = (double)((double)counter / (double)m);
cout << counter << endl;
cout << "查找失败的ASL为 " << setprecision(5) << fixed << fail_asl << endl;
cout << counter << endl;
}
//主函数
int main() {
cout << "请输入用户个数: "<<"\n";
cin >> n;
n1 = n; n2 = n;
m = confirm(n + 10); //确定散列表的大小
cout << "散列表大小为" << m << endl;
while (1) {
int counter(0);
cout << "* * * * * * * * * * * * * " << endl;
cout << "* * * 欢迎使用电话号码查询系统 * * * " << endl;
cout << "* *" << endl;
cout << "* *1.根据电话号码构建散列表 * *" << endl;
cout << "* *2.根据用户名构建散列表 * *" << endl;
cout << "* *3.根据电话号码查询相关信息 * *"<<endl;
cout << "* *4.根据用户名查询相关信息 * *" << endl;
cout << "* *5.根据电话号码插入用户信息 * *"<<endl;
cout << "* *6.根据用户名插入用户信息 * *" << endl;
cout << "* *7.根据电话号码删除散列表信息 * *" << endl;
cout<< "* *8.根据用户名删除散列表信息 * *" << endl;
cout << "* *9.显示电话号码散列表信息 * * "<<endl;
cout << "* *10.显示用户名散列表信息 * *" << endl;
cout << "* *11.求电话号码散列表查找成功的ASL *" << endl;
cout << "* *12.求用户名散列表查找成功的ASL * *" << endl;
cout << "* *13.求电话号码散列表查找失败的ASL * *" << endl;
cout << "* *14.求用户名散列表查找失败的ASL * *" << endl;
cout << "* *15.清屏 * *"<<endl;
cout << "* *16.安全退出 * *" << endl;
cout << " * *" << endl;
cout << "* * * * * * * * * * * * * " << endl;
cout << "请输入数字进行操作 "<<endl;
cin >> counter;
switch (counter) {
case 1: {
init1();
cout << endl << endl;
}; break;
case 2: {
init2();
cout << endl << endl;
}; break;
case 3: {
print1();
cout << endl << endl;
}; break;
case 4: {
print2();
cout << endl << endl;
}; break;
case 5: {
insert1();
cout << endl << endl;
}; break;
case 6: {
insert2();
cout << endl << endl;
}; break;
case 7: {
Delete1();
cout << endl << endl;
}; break;
case 8: {
Delete2();
cout << endl << endl;
}; break;
case 9: {
fun1();
cout << endl << endl;
}; break;
case 10: {
fun2();
cout << endl << endl;
}; break;
case 11: {
succ_asl1();
cout << endl << endl;
}; break;
case 12: {
succ_asl2();
cout << endl << endl;
}; break;
case 13: {
fail_asl1();
cout << endl << endl;
}; break;
case 14: {
fail_asl2();
cout << endl << endl;
}; break;
case 15: {
system("cls");
}; break;
case 16: {
return 0;
}; break;
}
}
}