设每个记录有下列数据项:电话号码、用户名、住址。从键盘输入各记录,以用户名为关键字建立哈希表,哈希函数用除留取余数法构造,采用线性探测法解决冲突。可以插入、查找、删除并显示给定用户名的记录,并计算查找长度, 哈希表保存到文件中。用C语言实现
时间: 2024-02-01 15:14:54 浏览: 81
以下是基于题目要求的C语言实现:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LEN 20 // 字符串最大长度
#define TABLE_SIZE 13 // 哈希表大小
typedef struct Record {
char phone[MAX_LEN];
char name[MAX_LEN];
char address[MAX_LEN];
} Record;
int hash_func(char *str); // 哈希函数
void insert_record(Record *table, Record r); // 插入记录
int search_record(Record *table, char *name, int *length); // 查找记录
void delete_record(Record *table, char *name); // 删除记录
void display_table(Record *table); // 显示哈希表中的记录
void save_table(Record *table); // 保存哈希表到文件中
void load_table(Record *table); // 从文件中读取哈希表
int main() {
Record table[TABLE_SIZE] = {0}; // 初始化哈希表
load_table(table); // 从文件中读取哈希表
while (1) {
printf("1. Insert record\n");
printf("2. Search record\n");
printf("3. Delete record\n");
printf("4. Display table\n");
printf("5. Save table to file\n");
printf("6. Exit\n");
printf("Enter your choice: ");
int choice;
scanf("%d", &choice);
switch (choice) {
case 1: {
Record r;
printf("Enter phone number: ");
scanf("%s", r.phone);
printf("Enter name: ");
scanf("%s", r.name);
printf("Enter address: ");
scanf("%s", r.address);
insert_record(table, r);
break;
}
case 2: {
char name[MAX_LEN];
printf("Enter name to search: ");
scanf("%s", name);
int length;
int index = search_record(table, name, &length);
if (index != -1) {
printf("Record found at index %d, search length = %d\n", index, length);
printf("Phone number: %s\n", table[index].phone);
printf("Name: %s\n", table[index].name);
printf("Address: %s\n", table[index].address);
} else {
printf("Record not found\n");
}
break;
}
case 3: {
char name[MAX_LEN];
printf("Enter name to delete: ");
scanf("%s", name);
delete_record(table, name);
break;
}
case 4: {
display_table(table);
break;
}
case 5: {
save_table(table);
break;
}
case 6: {
save_table(table); // 退出前保存哈希表到文件中
exit(0);
}
default: {
printf("Invalid choice\n");
break;
}
}
}
return 0;
}
int hash_func(char *str) {
int hash_val = 0;
for (int i = 0; i < strlen(str); i++) {
hash_val += str[i];
}
return hash_val % TABLE_SIZE;
}
void insert_record(Record *table, Record r) {
int index = hash_func(r.name);
int count = 0;
while (table[index].name[0] != '\0') { // 线性探测法解决冲突
index = (index + 1) % TABLE_SIZE;
count++;
if (count == TABLE_SIZE) { // 哈希表已满
printf("Hash table full, cannot insert record\n");
return;
}
}
table[index] = r;
printf("Record inserted at index %d\n", index);
}
int search_record(Record *table, char *name, int *length) {
int index = hash_func(name);
int count = 0;
while (table[index].name[0] != '\0') { // 线性探测法解决冲突
if (strcmp(table[index].name, name) == 0) {
*length = count + 1;
return index;
}
index = (index + 1) % TABLE_SIZE;
count++;
if (count == TABLE_SIZE) { // 已遍历整个哈希表,未找到记录
break;
}
}
*length = count + 1;
return -1;
}
void delete_record(Record *table, char *name) {
int index = search_record(table, name, NULL);
if (index != -1) {
table[index].name[0] = '\0'; // 将该位置的记录删除
printf("Record deleted at index %d\n", index);
} else {
printf("Record not found\n");
}
}
void display_table(Record *table) {
printf("Index\tPhone number\tName\tAddress\n");
for (int i = 0; i < TABLE_SIZE; i++) {
printf("%d\t%s\t%s\t%s\n", i, table[i].phone, table[i].name, table[i].address);
}
}
void save_table(Record *table) {
FILE *fp = fopen("hash_table.txt", "w");
if (fp == NULL) {
printf("Error opening file\n");
return;
}
for (int i = 0; i < TABLE_SIZE; i++) {
fprintf(fp, "%s,%s,%s\n", table[i].phone, table[i].name, table[i].address);
}
fclose(fp);
printf("Hash table saved to file\n");
}
void load_table(Record *table) {
FILE *fp = fopen("hash_table.txt", "r");
if (fp == NULL) {
printf("Cannot find file, creating new hash table\n");
return;
}
char line[MAX_LEN * 3 + 2];
while (fgets(line, MAX_LEN * 3 + 2, fp) != NULL) {
Record r;
sscanf(line, "%[^,],%[^,],%[^\n]", r.phone, r.name, r.address);
insert_record(table, r);
}
fclose(fp);
printf("Hash table loaded from file\n");
}
```
注意,这个实现可能并不是最优的,例如我们可以将哈希表保存到文件中时使用更高效的二进制格式。此外,这个实现还存在一些问题,例如当哈希表已满时无法插入新记录,而且没有实现动态扩容。但是这个实现可以作为哈希表基础知识的一个参考。
阅读全文