444 lines
11 KiB
C++
444 lines
11 KiB
C++
#include <iostream>
|
||
#include "AddList.h"
|
||
#include "Hash.h"
|
||
#include "ArrayHash.h"
|
||
|
||
using namespace std;
|
||
|
||
typedef enum {Phone, Name} HashType;
|
||
HashType hash_type;
|
||
HashTable hash_table;
|
||
|
||
bool PutRecord(HashTable &hash_tabe, const char *key, AddList add, AddList &old_add, unsigned int (*Hash)(const char *key, int table_size) = ShiftHash) {
|
||
return Put(hash_tabe, key, add, old_add, Hash);
|
||
}
|
||
|
||
bool GetRecord(HashTable &hash_table, const char *key, AddList &add, unsigned int (*Hash)(const char *key, int table_size) = ShiftHash) {
|
||
return Get(hash_table, key, add, Hash);
|
||
}
|
||
|
||
bool RemoveRecord(HashTable &hash_table, const char *key, AddList &add, unsigned int (*Hash)(const char *key, int table_size) = ShiftHash) {
|
||
return Remove(hash_table, key, add, Hash);
|
||
}
|
||
|
||
void PrintLine() {
|
||
cout << "----------------------------------------------------" << endl;
|
||
}
|
||
|
||
void ClearTerminal() {
|
||
system("clear");
|
||
}
|
||
|
||
void PrintRecord(AddList add) {
|
||
cout << "---------------------------------------" << endl;
|
||
cout << "电话:" << add.phone_num << endl;
|
||
cout << "姓名:" << add.name << endl;
|
||
cout << "地址:" << add.address << endl;
|
||
cout << "---------------------------------------" << endl;
|
||
}
|
||
|
||
void AddRecordForm() {
|
||
ClearTerminal();
|
||
cout << "\n添加通讯录\n" << endl;
|
||
|
||
char phone_num[MAXPHONENUM];
|
||
char name[MAXNAME];
|
||
char address[MAXADDRESS];
|
||
char right[10];
|
||
|
||
cout << "\n电话号码:";
|
||
cin >> phone_num;
|
||
cout << "\n姓名:";
|
||
cin >> name;
|
||
cout << "\n通讯住址:";
|
||
cin >> address;
|
||
cout << "\n是否添加(Y 或 N):";
|
||
cin >> right;
|
||
|
||
if (right[0] == 'Y' || right[0] == 'y') {
|
||
AddList add(phone_num, name, address);
|
||
AddList old_add;
|
||
if (hash_type == Phone)
|
||
PutRecord(hash_table, add.phone_num, add, old_add);
|
||
else
|
||
PutRecord(hash_table, add.name, add, old_add);
|
||
|
||
cout << "\n已添加新记录:\n" << endl;
|
||
PrintRecord(add);
|
||
|
||
char continue_add[10];
|
||
cout << "\n是否继续添加(Y 或 N):";
|
||
cin >> continue_add;
|
||
|
||
if (continue_add[0] == 'Y' || continue_add[0] == 'y')
|
||
AddRecordForm();
|
||
else
|
||
MainForm();
|
||
} else
|
||
MainForm();
|
||
}
|
||
|
||
void QueryRecordForm() {
|
||
ClearTerminal();
|
||
cout << "\n查询通讯录\n" << endl;
|
||
|
||
cout << "1) 搜索电话\n" << endl;
|
||
cout << "2) 搜索姓名\n" << endl;
|
||
cout << "q) 返回\n" << endl;
|
||
cout << "\n> ";
|
||
|
||
char choose[10];
|
||
cin >> choose;
|
||
|
||
if (choose[0] == '1')
|
||
QueryRecordByPhoneNum();
|
||
else if (choose[0] == '2')
|
||
QueryRecordByName();
|
||
else
|
||
MainForm();
|
||
}
|
||
|
||
char g_phone[MAXNAME];
|
||
bool has_phone = false;
|
||
void TraverseFindPhone(AddList add) {
|
||
if (!strcmp(g_phone, add.phone_num)) {
|
||
PrintRecord(add);
|
||
has_phone = true;
|
||
}
|
||
}
|
||
|
||
void QueryRecordByPhoneNum() {
|
||
ClearTerminal();
|
||
cout << "\n输入电话号码查询记录\n" << endl;
|
||
char phone_num[MAXPHONENUM];
|
||
AddList add;
|
||
|
||
cout << "电话号码:";
|
||
cin >> phone_num;
|
||
|
||
if (hash_type == Phone) {
|
||
if (GetRecord(hash_table, phone_num, add)) {
|
||
cout << endl;
|
||
PrintRecord(add);
|
||
cout << endl;
|
||
} else {
|
||
cout << "\n该电话不存在\n" << endl;
|
||
}
|
||
} else {
|
||
strcpy(g_phone, phone_num);
|
||
TraverseHashTable(hash_table, TraverseFindPhone);
|
||
if (!has_phone)
|
||
cout << "\n该电话不存在\n" << endl;
|
||
}
|
||
|
||
char choose[10];
|
||
cout << "是否继续查询(Y 或 N):";
|
||
cin >> choose;
|
||
|
||
if (choose[0] == 'Y' || choose[0] == 'y')
|
||
QueryRecordByPhoneNum();
|
||
else
|
||
QueryRecordForm();
|
||
}
|
||
|
||
char g_name[MAXNAME];
|
||
bool has_name = false;
|
||
void TraverseFindName(AddList add) {
|
||
if (!strcmp(g_name, add.name)) {
|
||
PrintRecord(add);
|
||
has_name = true;
|
||
}
|
||
}
|
||
|
||
void QueryRecordByName()
|
||
{
|
||
ClearTerminal();
|
||
cout << "\n输入姓名查询记录\n" << endl;
|
||
|
||
char name[MAXPHONENUM];
|
||
AddList add;
|
||
|
||
cout << "姓名:";
|
||
cin >> name;
|
||
|
||
if (hash_type == Name) {
|
||
if (GetRecord(hash_table, name, add)) {
|
||
cout << endl;
|
||
PrintRecord(add);
|
||
cout << endl;
|
||
} else {
|
||
cout << "\n该姓名不存在\n" << endl;
|
||
}
|
||
} else {
|
||
strcpy(g_name, name);
|
||
TraverseHashTable(hash_table, TraverseFindName);
|
||
if (!has_name)
|
||
cout << "\n该姓名不存在\n" << endl;
|
||
}
|
||
|
||
char choose[10];
|
||
cout << "是否继续查询(Y 或 N):";
|
||
cin >> choose;
|
||
|
||
if (choose[0] == 'Y' || choose[0] == 'y')
|
||
QueryRecordByName();
|
||
else
|
||
QueryRecordForm();
|
||
}
|
||
|
||
void VisitRecord(AddList add) {
|
||
printf(" %-15s%-20s%-30s\n", add.phone_num, add.name, add.address);
|
||
}
|
||
|
||
void DisplayAllRecord() {
|
||
ClearTerminal();
|
||
PrintLine();
|
||
printf(" %-15s %-20s%-30s\n\n", "电话号码", "姓名", "通讯地址");
|
||
TraverseHashTable(hash_table, VisitRecord);
|
||
PrintLine();
|
||
|
||
cout << "\n\n按任意键返回..." << endl;
|
||
getchar();
|
||
getchar();
|
||
MainForm();
|
||
}
|
||
|
||
void ImportRecordsFromFile() {
|
||
ClearTerminal();
|
||
FILE* file = fopen("./records.txt", "r");
|
||
if (file) {
|
||
while (!feof(file)) {
|
||
AddList record, old_record;
|
||
fscanf(file, "%s%s%s", record.phone_num, record.name, record.address);
|
||
if (hash_type == Phone)
|
||
PutRecord(hash_table, record.phone_num, record, old_record);
|
||
else
|
||
PutRecord(hash_table, record.name, record, old_record);
|
||
}
|
||
|
||
cout << "\n导入成功" << endl;
|
||
fclose(file);
|
||
} else {
|
||
cout << "\n导入失败..." << endl;
|
||
}
|
||
|
||
cout << "\n\n按任意键返回..." << endl;
|
||
getchar();
|
||
getchar();
|
||
MainForm();
|
||
}
|
||
|
||
void GenerateRandomRecords(int total_num, AddList Records[]) {
|
||
const char char_set[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2',
|
||
'3', '4', '5', '6', '7', '8', '9', '\0'};
|
||
int char_set_len = strlen(char_set);
|
||
|
||
srand(time(NULL));
|
||
|
||
for (int i = 0; i < total_num; i++) {
|
||
char key[MAXKEYLEN] = {'\0'};
|
||
int len = rand() % MAX_RANDOM_STR_SIZE + 1;
|
||
|
||
for (int i = 0; i < len; i++) {
|
||
int ci = rand() % char_set_len;
|
||
key[i] = char_set[ci];
|
||
}
|
||
AddList add(key, key, key);
|
||
Records[i] = add;
|
||
}
|
||
}
|
||
|
||
void HashFuncCompare() {
|
||
ClearTerminal();
|
||
cout << "\n不同哈希函数性能对比\n" << endl;
|
||
|
||
int total_num;
|
||
|
||
double sum_asl = 0, shift_asl = 0, elf_asl = 0;
|
||
double sum_size = 0, shift_size = 0, elf_size = 0;
|
||
cout << "输入随机生成数据个数:";
|
||
cin >> total_num;
|
||
|
||
if (total_num <= 0)
|
||
total_num = 100;
|
||
|
||
AddList *Records = new AddList[total_num], old_add;
|
||
GenerateRandomRecords(total_num, Records);
|
||
|
||
HashTable sum_hash, shift_hash, elf_hash;
|
||
InitHashTable(sum_hash, 32);
|
||
InitHashTable(shift_hash, 32);
|
||
InitHashTable(elf_hash, 32);
|
||
|
||
for (int i = 0; i < total_num; i++) {
|
||
Put(sum_hash, Records[i].phone_num, Records[i], old_add, SumHash);
|
||
Put(shift_hash, Records[i].phone_num, Records[i], old_add, ShiftHash);
|
||
Put(elf_hash, Records[i].phone_num, Records[i], old_add, ELFHash);
|
||
}
|
||
|
||
sum_size = sum_hash.size;
|
||
shift_size = shift_hash.size;
|
||
elf_size = elf_hash.size;
|
||
|
||
sum_asl = GetASL(sum_hash, SumHash);
|
||
shift_asl = GetASL(shift_hash, ShiftHash);
|
||
elf_asl = GetASL(elf_hash, ELFHash);
|
||
|
||
DelHashTable(sum_hash);
|
||
DelHashTable(shift_hash);
|
||
DelHashTable(elf_hash);
|
||
|
||
cout << "\n统计结果:\n" << endl;
|
||
PrintLine();
|
||
printf("%10s\t%10s\t%10s\n", "Hash Fun", "Size", "ASL");
|
||
PrintLine();
|
||
printf("%10s\t%10.2f\t%10.2f\n", "SumHash", sum_size, sum_asl);
|
||
printf("%10s\t%10.2f\t%10.2f\n", "ShiftHash", shift_size, shift_asl);
|
||
printf("%10s\t%10.2f\t%10.2f\n", "ELFHash", elf_size, elf_asl);
|
||
PrintLine();
|
||
|
||
cout << "\n\n按任意键返回..." << endl;
|
||
getchar();
|
||
getchar();
|
||
MainForm();
|
||
}
|
||
|
||
void ConflictMethodCompare() {
|
||
ClearTerminal();
|
||
cout << "\n不同哈希函数性能对比\n" << endl;
|
||
|
||
int total_num;
|
||
|
||
double list_asl = 0, array_asl = 0;
|
||
double list_size = 0, array_size = 0;
|
||
cout << "输入随机生成数据个数:";
|
||
cin >> total_num;
|
||
|
||
if (total_num <= 0)
|
||
total_num = 100;
|
||
|
||
AddList *Records = new AddList[total_num], old_add;
|
||
GenerateRandomRecords(total_num, Records);
|
||
|
||
HashTable list_hash;
|
||
ArrayHashTable array_hash;
|
||
InitHashTable(list_hash, 32);
|
||
InitArrayHashTable(array_hash, total_num);
|
||
|
||
for (int i = 0; i < total_num; i++) {
|
||
Put(list_hash, Records[i].phone_num, Records[i], old_add, ShiftHash);
|
||
LinearPut(array_hash, Records[i].phone_num, Records[i], old_add);
|
||
}
|
||
|
||
list_size = list_hash.size;
|
||
array_size = array_hash.size;
|
||
|
||
list_asl = GetASL(list_hash, ShiftHash);
|
||
|
||
int sum = 0;
|
||
for (int i = 0; i < total_num; i++) {
|
||
int num;
|
||
AddList add;
|
||
LinearGetNum(array_hash, Records[i].phone_num, add, num);
|
||
sum += num;
|
||
}
|
||
array_asl = 1.0*sum / total_num;
|
||
|
||
DelHashTable(list_hash);
|
||
DelArrayHashTable(array_hash);
|
||
|
||
cout << "\n统计结果:\n" << endl;
|
||
PrintLine();
|
||
printf("%10s\t%10s\t%10s\n", "Conflict Method", "Size", "ASL");
|
||
PrintLine();
|
||
printf("%10s\t%10.2f\t%10.2f\n", "List Hash", list_size, list_asl);
|
||
printf("%10s\t%10.2f\t%10.2f\n", "Linear Hash", array_size, array_asl);
|
||
PrintLine();
|
||
|
||
cout << "\n\n按任意键返回..." << endl;
|
||
getchar();
|
||
getchar();
|
||
MainForm();
|
||
}
|
||
|
||
void MainForm() {
|
||
ClearTerminal();
|
||
PrintLine();
|
||
|
||
cout << "\n\n1) 添加通讯录\n" << endl;
|
||
cout << "2) 查询通讯录\n" << endl;
|
||
cout << "3) 查看全部通讯录\n" << endl;
|
||
cout << "4) 批量导入通讯录\n" << endl;
|
||
cout << "5) 不同哈希函数比较\n" << endl;
|
||
cout << "6) 不同冲突解决方法比较\n" << endl;
|
||
cout << "q) 退出\n\n" << endl;
|
||
|
||
PrintLine();
|
||
cout << "\n> ";
|
||
|
||
char op[10];
|
||
cin >> op;
|
||
|
||
if (op[0] == '1')
|
||
AddRecordForm();
|
||
else if (op[0] == '2')
|
||
QueryRecordForm();
|
||
else if (op[0] == '3')
|
||
DisplayAllRecord();
|
||
else if (op[0] == '4')
|
||
ImportRecordsFromFile();
|
||
else if (op[0] == '5')
|
||
HashFuncCompare();
|
||
else if (op[0] == '6')
|
||
ConflictMethodCompare();
|
||
else
|
||
return;
|
||
}
|
||
|
||
void ChooseHashType() {
|
||
ClearTerminal();
|
||
PrintLine();
|
||
|
||
cout << "\n\n选择建立哈希索引类型\n" << endl;
|
||
cout << "1) 以 电话号码 建立\n" << endl;
|
||
cout << "2) 以 姓名 建立\n" << endl;
|
||
cout << "q) 退出\n\n" << endl;
|
||
|
||
PrintLine();
|
||
cout << "\n> ";
|
||
|
||
char op[10];
|
||
cin >> op;
|
||
|
||
if (op[0] == '1')
|
||
hash_type = Phone;
|
||
else if (op[0] == '2')
|
||
hash_type = Name;
|
||
else
|
||
return;
|
||
|
||
InitHashTable(hash_table, 30);
|
||
MainForm();
|
||
}
|
||
|
||
void WelcomeForm() {
|
||
ClearTerminal();
|
||
PrintLine();
|
||
cout << "\n\n 哈希电话号码查找系统 \n\n";
|
||
cout << " 高天 \n\n";
|
||
cout << " 软件1601 \n\n";
|
||
cout << " 201616030213 \n\n";
|
||
PrintLine();
|
||
getchar();
|
||
ChooseHashType();
|
||
}
|
||
|
||
|
||
int main()
|
||
{
|
||
WelcomeForm();
|
||
|
||
return 0;
|
||
}
|