#include <stdio.h>
#include <string.h>
#pragma warning(disable:4996)
#define N 20
#define Bool int
#define True 1
#define False 0
typedef struct AddressBook
{
char _name[N];
char _sex[2];
int _age;
char _number[20];
char _adress[100];
}AB;
typedef struct HashTable
{
const AB* *mTbl; // 哈希表
int mSize; // 表尺寸
int mStep; // 冲突后的步进值
int mCmpCount; // 查找是记录查找次数(题目要求的没其他用)
}HashTable;
void AddPerson();//1、添加联系人信息
void DeletePerson();//2、删除指定联系人信息
void FindPerson();//3、查找指定联系人信息
void ChangePerson();//4、修改指定联系人信息
void PrintfAllPerson();//5、显示所有联系人信息
void ClearAllPerson();//6、清空所有联系人
void SortPersonByName();//7、以名字排序所有联系人
void FindPerson_hash(HashTable* table);//9.哈希查找人
void AddPerson(struct AddressBook * p, int& cnt)
{
AB* pTemp = p;
int i = 0;
char name[N];
char sex[2];
int age;
char number[20];
char address[100];
//for(i =0;i<cnt;i++){
// pTemp++;
//}
printf("Please enter name:");
scanf("%s", name);
strcpy(pTemp[cnt]._name, name);
printf("Please enter sex:");
scanf("%s", sex);
strcpy(pTemp[cnt]._sex, sex);
printf("Please enter age:");
scanf("%d", &age);
pTemp[cnt]._age = age;
printf("Please enter number:");
scanf("%s", &number);
strcpy(pTemp[cnt]._number, number);
printf("Please enter address:");
scanf("%s", address);
strcpy(pTemp[cnt]._adress, address);
cnt++;
printf("储存成功!\n");
}
void DeletePerson(AB* p, int& cnt)
{
AB* pTemp = p;
char ptempname[20];
printf("请输入想要删除联系人的名字:\n");
scanf("%s", ptempname);
for (int i = 0; i < cnt; i++){
if (strcmp(pTemp[i]._name, ptempname) == 0){
printf("这是第%d个联系人:\n", i + 1);
printf("姓名:%s\n", p[i]._name);
printf("性别:%s\n", p[i]._sex);
printf("年纪:%d\n", p[i]._age);
printf("电话:%s\n", p[i]._number);
printf("住址:%s\n", p[i]._adress);
}
}
printf("请输入想要更改联系人的编号:\n");
int number = 0;
scanf("%d", &number);
strcpy(p[number - 1]._name, p[cnt - 1]._name);
strcpy(p[number - 1]._sex, p[cnt - 1]._sex);
p[number - 1]._age = p[cnt - 1]._age;
strcpy(p[number - 1]._number, p[cnt - 1]._number);
strcpy(p[number - 1]._adress, p[cnt - 1]._adress);
cnt--;
printf("修改成功");
}
void FindPerson(AB* p, int cnt)
{
int flag = 0;
AB* pTemp = p;
char name[10];
printf("请输入你想要查询联系人的名字:");
scanf("%s", &name);
for (int i = 0; i <= cnt; i++){
if (strcmp(pTemp[i]._name, name) == 0){
flag = 1;
printf("姓名:%s\n", p[i]._name);
printf("性别:%s\n", p[i]._sex);
printf("年纪:%d\n", p[i]._age);
printf("电话:%s\n", p[i]._number);
printf("住址:%s\n", p[i]._adress);
}
}
if (flag == 0){
printf("没有此联系人,请重新输入!\n");
}
}
void ChangePerson(AB* p, int cnt)
{
AB* pTemp = p;
char name[10];
printf("请输入你想修改联系人的名字:");
scanf("%s", &name);
for (int i = 0; i <= cnt; i++){
if (strcmp(pTemp[i]._name, name) == 0){
printf("这是第%d个联系人:\n", i + 1);
printf("姓名:%s\n", p[i]._name);
printf("性别:%s\n", p[i]._sex);
printf("年纪:%d\n", p[i]._age);
printf("电话:%s\n", p[i]._number);
printf("住址:%s\n", p[i]._adress);
}
}
int num;
printf("请输入你要修改的联系人编号:");
scanf("%d", &num);
char name2[N];
char sex[2];
int age;
char number[20];
char address[100];
printf("Please enter new name:");
scanf("%s", name2);
strcpy(pTemp[num - 1]._name, name2);
printf("Please enter new sex:");
scanf("%s", sex);
strcpy(pTemp[num - 1]._sex, sex);
printf("Please enter new age:");
scanf("%d", &age);
pTemp[num - 1]._age = age;
printf("Please enter new number:");
scanf("%s", &number);
strcpy(pTemp[num - 1]._number, number);
printf("Please enter new address:");
scanf("%s", address);
strcpy(pTemp[num - 1]._adress, address);
printf("修改成功!");
}
void PrintfAllPerson(AB* p, int cnt)
{
AB* pTemp = p;
int i = 0;
if (cnt == 0){
printf("空通讯录!\n");
return;
}
for (i = 0; i < cnt; i++){
printf("第%d个联系人:\n", i + 1);
printf("姓名:%s\n", pTemp[i]._name);
printf("性别:%s\n", pTemp[i]._sex);
printf("年纪:%d\n", pTemp[i]._age);
printf("电话:%s\n", pTemp[i]._number);
printf("住址:%s\n", pTemp[i]._adress);
}
}
void ClearAllPerson(AB*& p, int& cnt)
{
int i = 0;
AB* pTemp = p;
for (i = 0; i < cnt; i++){
strcpy(p[i]._adress, " ");
p[i]._age = 0;
strcpy(p[i]._name, " ");
strcpy(p[i]._number, " ");
strcpy(p[i]._sex, " ");
}
printf("通讯录已清空!\n");
cnt = 0;
}
void swap(char* a, char* p)
{
char newname[N];
strcpy(newname, a);
strcpy(a, p);
strcpy(p, newname);
}
void SortPersonByName(AB* p, int cnt)
{
AB* pTemp = p;
for (int i = 0; i < cnt; i++){
for (int j = i; j < cnt; j++){
if (strcmp(pTemp[i]._name, pTemp[j]._name) >= 0){
swap(pTemp[i]._name, pTemp[j]._name);
}
}
}
printf("排序成功!\n");
}
void GUI()
{
printf("***************************************************\n");
printf("* 1、添加联系人 2、删除联系人 *\n");
printf("* 3、查找联系人 4、修改联系人 *\n");
printf("* 5、显示联系人 6、清空联系人 *\n");
printf("* 7、排序联系人 0、退出 *\n");
printf("* 8、创建哈希表 9、哈希查找电话 *\n");
printf("***************************************************\n");
}
void dtor(HashTable *table);// 哈希表构造器
void ctor(HashTable *table, int tableSize, int step);// 哈希表析构器
Bool insert_more(HashTable* table, AB abTbl[], int cnt);// 插入一堆
Bool insert_one(HashTable* table, const AB* ab);// 插入一个
Bool delete_one(HashTable* table, const char number[]);// 删除一个
int find_one(HashTable* table, const char number[]);// 返回hash表中的下标, 没找到返回 -1
int main()
{
struct AddressBook s[1000];
HashTable ht; ctor(&ht, 20, 3);
GUI();
int select = 0;
int cnt = 0;
if (FILE* fp = fopen("txl.txt", "rb")){
fread(&cnt, 1, sizeof(cnt), fp);
fread(s, 1, sizeof(AB)*cnt, fp);
fclose(fp);
}
Bool bHashOk = False;
AB* pCur = s;
while (select != EOF){
printf("请输入您的选择:");
scanf("%d", &select);
switch (select){
case 1:
AddPerson(pCur, cnt);
GUI();
continue;
case 2:
DeletePerson(pCur, cnt);
continue;
case 3:
FindPerson(pCur, cnt);
GUI();
continue;
case 4:
ChangePerson(pCur, cnt);
GUI();
continue;
case 5:
PrintfAllPerson(pCur, cnt);
GUI();
continue;
case 6:
ClearAllPerson(pCur, cnt);
GUI();
continue;
case 7:
SortPersonByName(pCur, cnt);
GUI();
continue;
case 8:
if (bHashOk){ dtor(&ht); ctor(&ht, 20, 3); }
bHashOk = insert_more(&ht, pCur, cnt);
GUI();
continue;
case 9:
if (bHashOk){
FindPerson_hash(&ht);
GUI();
}
else{
printf("没有构建哈希表!\n");
}
continue;
case 0:
printf("success exit!\n");
break;
default:
printf("Error input,please input the right number\n");
continue;
}
break;
}
dtor(&ht);
if (FILE* fp = fopen("txl.txt", "wb")){
fwrite(&cnt, 1, sizeof(cnt), fp);
fwrite(s, 1, sizeof(AB)*cnt, fp);
fclose(fp);
}
return 0;
}
void FindPerson_hash(HashTable* table)
{
char number[10];
printf("请输入你想要查询联系人的电话:");
scanf("%s", &number);
int idx = find_one(table, number);
if (idx != -1){
const AB* p = table->mTbl[idx];
printf("姓名:%s\n", p[0]._name);
printf("性别:%s\n", p[0]._sex);
printf("年纪:%d\n", p[0]._age);
printf("电话:%s\n", p[0]._number);
printf("住址:%s\n", p[0]._adress);
}
else{
printf("没有此联系人,请重新输入!\n");
}
}
//-----------hash-----------
#include <stdlib.h>
void dtor(HashTable *table)
{
//for (int i = table->mSize; i--;){
// if (const AB* p = table->mTbl[i])
// free((char*)p);
//}
free(table->mTbl);
}
void ctor(HashTable *table, int tableSize, int step)
{
table->mStep = step;
table->mSize = tableSize;
table->mTbl = (const AB* *)malloc(sizeof(const AB*)*tableSize);
memset(table->mTbl, 0, sizeof(const AB*)*tableSize);
}
//int calcHash(const char *key)
//{
// unsigned int nr = 1u, nr2 = 4u;
// while (char ch = *key++){
// nr ^= (((nr & 63u) + nr2)*((unsigned int)ch)) + (nr << 8);
// nr2 += 3u;
// }
// return (int)nr;
//}
//字符串哈希值计算
int calcHash(const char* str, int mod)
{
int mix = 0;
while (char ch = *str++){
int num = 0;
if (' ' == ch) num = 113;
else if ('a' <= ch && ch <= 'z') num = (int)(ch - 'a');
else if ('A' <= ch && ch <= 'Z') num = (int)(ch - 'A') + 26;
else if ('0' <= ch && ch <= '9') num = (int)(ch - '0') + 52;
else return 0;
mix <<= 6;
mix |= num;
mix %= mod;
}
return mix;
}
// 插入一个元素
Bool insert_one(HashTable* table, const AB* ab)
{
//哈希值计算
int hash = calcHash(ab->_number, table->mSize);
int head = hash % table->mSize;
int i = head;
// 冲突解决式插入
do{
if (table->mTbl[i] < (const AB*)2)
i = (i + table->mStep) % table->mSize;
else{
table->mTbl[i] = ab;
return True;
}
} while (head != i);
return False;
}
// 返回hash表中的下标, 没找到返回 -1
int find_one(HashTable* table, const char number[])
{
table->mCmpCount = 0;
int hash = calcHash(number, table->mSize);
int head = hash % table->mSize;
int i = head;
while (table->mTbl[i]){
table->mCmpCount++;
if ((table->mTbl[i] != (const AB*)1) &&
(strcmp(number, table->mTbl[i]->_number) == 0))
return i;
i = (i + table->mStep) % table->mSize;
if (head != i) break;
}
return -1;
}
// 删除一个元素
Bool delete_one(HashTable* table, const char number[])
{
int idx = find_one(table, number);
if (idx != -1){ table->mTbl[idx] = (const AB*)1; } // 标志为僵尸节点
return (Bool)(idx != -1);
}
// 调节哈希表尺寸
Bool resize(HashTable* table, int mulK)
{
// 构造
HashTable ht;
ctor(&ht, table->mSize * mulK, table->mStep);
// 插入新表中去
for (int i = table->mSize; i--;){
if (table->mTbl[i] < (const AB*)2) continue;
if (insert_one(&ht, table->mTbl[i])) continue;
dtor(&ht); return False;
}
// 清楚旧表
memset(table->mTbl, 0, sizeof(const char*)*table->mSize);
dtor(table);
table->mSize = ht.mSize;
table->mTbl = ht.mTbl;
return True;
}
Bool insert_more(HashTable* table, AB abTbl[], int cnt)
{
for (int i = 0; i < cnt; ++i){
if (!insert_one(table, &abTbl[i])){
int tryCnt = 8, mulK = 1;
do{
if (!resize(table, mulK *= 2)) continue;
if (!insert_one(table, &abTbl[i])) continue;
break;
} while (--tryCnt);
if (0 == tryCnt){
printf("hash function too bad, replace one\n");
return False;
}
}
}
return True;
}