#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; } } }