通讯录管理系统 (数据结构与算法课设)(哈希表存储)

    为数据结构与算法关于通讯录管理系统的解决方案。采用顺序表和二次散列存储的方式,使用表格的输出形式并向文件导出。

目录

设计内容和要求

代码实现

1.结构体实现

 2.增删改查操作

 添加联系人

删除联系人

修改联系人

查找联系人

3.打印输入和文件导入

打印通讯录

导入信息到文件

4.菜单函数和主函数

5.**完整代码


设计内容和要求

设计内容:

    设计散列表实现通讯录查找系统。

(1) 每个记录包括数据项:电话号码、用户名、地址;

(2) 从键盘输入记录,分别以电话号码为关键字建立散列表;

(3)查找并显示给定号码的记录;

(4) 通讯录信息文件保存。

设计要求:

(1) 符合课题要求,实现相应功能;

(2) 要求界面友好美观,操作方便易行;

(3) 注意程序的实用性、安全性。

3.设计工作任务及工作量的要求

(1) 选择合适的数据结构,并定义数据结构的结构体;

(2) 根据程序所要完成的基本要求和程序实现提示,设计出完整的算法;

代码实现

完整代码在最后,时间有限,只完整了基本函数,还存在不足和有待优化改正的地方,欢迎评论讨论和分享。

1.结构体实现

struct list {
	elemtype a[Length_1];
	elemtype NaMe[Length_2];
	elemtype address[Length_3];
	int f;
};
struct sqstack {
	struct list* base;
	int i;
};

struct sqstack T;

代码中使用了两个全局变量,一个是散列表,另一个NUM_T用来记录表中联系人个人数

 2.增删改查操作

 添加联系人
void store(elemtype* a, elemtype* NaMe, elemtype* address) {
	int d[50];
	int mainnumber;
	mainnumber = (int)(a[0]) + (int)(a[3]) + (int)(a[7]); /*此处构造哈希函数,用关键字 037 位*/
	T.i = mainnumber % MAX_size;
	int j = 1;
	(T.base + T.i)->f = 0;
	while (1) {
		if ((T.base + T.i)->f == 0) {
			strcpy((T.base + T.i)->a, a);
			strcpy((T.base + T.i)->NaMe, NaMe);
			strcpy((T.base + T.i)->address, address);
			(T.base + T.i)->f = 1;
			break;
		}
		T.i = (mainnumber % 20 + d[j]) % 20;
		j++;
	}
}
void addContact() {
	void menu();
	printf("请输入信息:\n\n(输入后自动保存一次)\n\n");
	elemtype a[12];
	elemtype NaMe[15];
	elemtype address[15];
	int put;
	
	while (1) {
		printf("请输入联系人的联系方式\n");
		scanf("%s", a);
		printf("请输入联系人姓名\n");
		scanf("%s", NaMe);
		printf("请输入联系人地址\n");
		scanf("%s", address);	
		store(a, NaMe, address);
		printf("输入的数据已经保存,请输入1继续输入或者输入0结束\n******************************\n");
		scanf("%d",&put);
		if (put == 0) { break; }
		else if (put == 1) { continue;}
	
	}
	NUM_T++;
	menu();
}

         这里添加联系人信息后,使用store函数保存到散列表中,新增函数中实际还存在三个可以改动优化的地方。一是判断重复联系人输入,而是对于电话号码输入是否正确的判断,三是对于终止输入只使用1和0判断并不安全。

        对于改动的一些思路:一,由于是采用散列表存储,可以在输入电话号后先判断散列表对应位置是否已经存在元素。没有就说明是新添加的联系人,如果有,可以让用户选择调用修改。二,电话号码是11位(一般而言)所以判断可以通过去计算数组长度或者使用strlen去计算后于“11111111111”比较。三,目前没有更好的方法去改正,如果有好想法,欢迎评论指教。

删除联系人
void deleteContact() {
	void menu();
	int i;
	int ff = 0;
	int b;
	elemtype a[15];
	printf("输入 1 按姓名删除,输入 2 按电话删除,输入 3 按地址删除\n");
	scanf("%d", &b);
	switch (b) {
	case 1:
		printf("请输入姓名\n");
		scanf("%s", a);
		for (i = 0; i < 20; i++)
			if (strcmp(a, (T.base + i)->NaMe) == 0) {
				(T.base + i)->f = 0;
				printf("已删除: %s %s %s\n", (T.base + i)->NaMe, (T.base + i)->a, (T.base +
					i)->address);
				ff = 1;
			}
		if (ff == 0)
			printf("找不到\n");
		break;
	case 2:
		printf("请输入电话号码\n");
		scanf("%s", a);
		for (i = 0; i < 20; i++)
			if (strcmp(a, (T.base + i)->a) == 0) {
				(T.base + i)->f = 0;
				printf("已删除: %s %s %s\n", (T.base + i)->NaMe, (T.base + i)->a, (T.base +
					i)->address);
				ff = 1;
			}
		if (ff == 0)
			
  • 23
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#include #include #include using namespace std; #define NULL 0 unsigned int key; //用来输入/输出文件流类 unsigned int key2; //key和key2分别是用做了电话号码和姓名的关键字 int *p; struct node //新建节点(用户姓名、地址、电话号码、指向下一个结点的指针 ) { char name[8],address[20]; char num[11]; node * next; }; typedef node* pnode; typedef node* mingzi; //声明了名字和电话两个指针 node **phone; node **nam; node *a; void hash(char num[11]) //以电话号码为关键字建立哈希函数 { int i = 3; key=(int)num[2]; while(num[i]!=NULL) { key+=(int)num[i]; i++; } key=key%20; } void hash2(char name[8]) //姓名为关键字建立哈希函数 { int i = 1; key2=(int)name[0]; while(name[i]!=NULL) { key2+=(int)name[i]; i++; } key2=key2%20; } //强制类型转换,将用户名的每一个字母的ASCLL码值相加并且除以20后的余数 node* input() //输入节点信息 ,建立结点,并将结点的next指针指空 { node *temp; temp = new node; temp->next=NULL; cout<<"输入姓名:"<>temp->name; cout<<"输入地址:"<>temp->address; cout<<"输入电话:"<>temp->num; return temp; } //对于指针类型返回的是地址 int apend() //添加节点 { node *newphone; node *newname; newphone=input(); newname=newphone; newphone->next=NULL; newname->next=NULL; hash(newphone->num); //利用哈希函数计算出对应关键字的存储地址 hash2(newname->name); newphone->next = phone[key]->next; //利用电话号码为关键字插入 phone[key]->next=newphone; //是采用链地址法,拉链法处理冲突的散列表结构 newname->next = nam[key2]->next; //利用用户名为关键字插入 nam[key2]->next=newname; return 0; } void create() //新建节点 { int i; phone=new pnode[20]; //动态创建对象数组,C++课本P188页 for(i=0;inext=NULL; } } void create2() //新建节点 { int i; nam=new mingzi[20]; for(i=0;inext=NULL; } } void list() //显示列表 { int i; node *p; for(i=0;inext; while(p) { cout<name<<'_'<address<<'_'<num<next; } } } void list2() //显示列表 { int i; node *p; for(i=0;inext; while(p) { cout<name<<'_'<address<<'_'<num<next; } } } void find(char num[11]) //在以电话号码为关键字的哈希表中查找用户信息 { hash(num); node *q=phone[key]->next; while(q!= NULL) { if(strcmp(num,q->num)==0) break; q=q->next; } if(q) cout<name<<"_" <address<<"_"<num<<endl; else cout<<"无此记录"<next; while(q!= NULL) { if(strcmp(name,q->name)==0) break; q=q->next; } if(q) cout<name<<"_" <address<<"_"<num<<endl; else cout<<"无此记录"<<endl; } void save() //保存用户信息 { int i; node *p; for(i=0;inext; while(p) { fstream iiout("out.txt", ios::out); //创建一个文件流对象:iiout iiout<name<<"_"<address<<"_"<num<next; } } } void menu() //菜单 { cout<<" 哈希表通讯录"<<endl; cout<<" 0.添加记录"<<endl; cout<<" 2.姓名散列"<<endl; cout<<" 3.查找记录"<<endl; cout<<" 4.号码散列"<<endl; cout<<" 5.清空记录"<<endl; cout<<" 6.保存记录"<<endl; cout<<" 7.退出系统"<>sel; if(sel==3) { cout<<"8姓名查询" <<endl;cout<<"9号码查询"<>b; if(b==9) {cout<<"请输入电话号码:"<>num; cout<<"输出查找的信息:"<<endl; find(num); } else {cout<<"请输入姓名:"<>name; cout<<"输出查找的信息:"<<endl; find2(name);}} if(sel==2) {cout<<"姓名散列结果:"<<endl; list2();} if(sel==0) {cout<<"请输入要添加的内容:"<<endl; apend();} if(sel==4) {cout<<"号码散列结果:"<<endl; list(); } if(sel==5) {cout<<"列表已清空:"<<endl; create();create2();} if(sel==6) { cout<<"通信录已保存:"<<endl; save();} if(sel==7) return 0; } return 0; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值