TreeNode.h:
/**********************************************************************************
* 基于二叉排序树的个人通信录
*
*
*
*
*
* 文 件: Treenode.h
* 作 者: 邹亚鹏
* 部 门: 南京工程学院
* 编写日期: 20012.07.19
* 模块版本:
* 修改记录:
* ================================================================================
* 版 本| 日 期 | 修改人 |
* ================================================================================
* | | |
* | | |
* | | |
* ================================================================================
*
*
*
**********************************************************************************/
#define N 50
/********************定义二叉树结点数据结构体**********************/
typedef struct student
{
char name[N];
char studentID[N];
char brithday[N];
char tele[N];
}TreeData;
/**********************定义二叉树结点结构体************************/
typedef struct treenode
{
TreeData * stuinfo;
struct treenode * leftchild;
struct treenode * rightchild;
}TREENODE;
Addressbook.h:
/**********************************************************************************
* 基于二叉排序树的个人通信录
*
*
*
*
*
* 文 件: Addressbook.h
* 作 者: 邹亚鹏
* 部 门: 南京工程学院
* 编写日期: 20012.07.19
* 模块版本:
* 修改记录:
* ================================================================================
* 版 本| 日 期 | 修改人 |
* ================================================================================
* | | |
* | | |
* | | |
* ================================================================================
*
*
*
**********************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "Treenode.h"
/*********************************函数申明***************************************/
extern TREENODE * mycreatetree();
extern void myinsertnode(TREENODE *,TreeData *);
extern void mycopy(TreeData *,char *,char *,char *,char *);
extern void myeva(TreeData *);
extern void preorder(TREENODE *);
extern TREENODE *treeinit(TREENODE *);
extern TREENODE * mysearch(TREENODE *,char *);
extern int isfind(TREENODE *,char *);
extern int mycorrect(TREENODE *,char *);
extern TREENODE * findleaf(TREENODE *);
extern TREENODE * findparent(TREENODE *,TREENODE *);
extern void myremove(TREENODE *,char *);
Addressbook.c:
/**********************************************************************************
* 基于二叉排序树的个人通信录
*
*
*
*
*
* 文 件: Addressbook.c
* 作 者: 邹亚鹏
* 部 门: 南京工程学院
* 编写日期: 20012.07.19
* 模块版本:
* 修改记录:
* ================================================================================
* 版 本| 日 期 | 修改人 |
* ================================================================================
* | | |
* | | |
* | | |
* ================================================================================
*
*
*
**********************************************************************************/
#include "Addressbook.h"
/**********************************************************************************
* 赋值函数(添加学生时使用)
*描述:该函数用于给结构体数据赋值。
*
*参数: TreeData *dest
*
*返回值:无
*
*注意事项:
**********************************************************************************/
void myeva(TreeData *dest)
{
printf("请输入你要添加的姓名:");
scanf("%s",dest->name);
while(1) /*判断输入是否合法*/
{
printf("请输入你要添加的学号(20209XXXX):");
scanf("%s",dest->studentID);
if((strlen(dest->studentID) == 9) && (dest->studentID[0] == '2')&& (dest->studentID[1] == '0')&& (dest->studentID[2] == '2')&& (dest->studentID[3] == '0')&& (dest->studentID[4] == '9')&&((dest->studentID[5] <= '9')&&(dest->studentID[5] >= '0'))&&((dest->studentID[6] <= '9')&&(dest->studentID[6] >= '0'))&&((dest->studentID[7] <= '9')&&(dest->studentID[7] >= '0'))&&((dest->studentID[8] <= '9')&&(dest->studentID[8] >= '0')))
{
break; /*合法结束*/
}
else
{
printf("输入有误!\n");
printf("您输入的数据必须为20209XXXX的格式(XXXX为可变数)\n");
}
}
while(1) /*判断输入是否合法*/
{
printf("请输入你要添加的生日(XXXX-XX-XX):");
scanf("%s",dest->brithday);
if((strlen(dest->brithday) == 10) && ((dest->brithday[0] <= '9')&&(dest->brithday[0] >= '0'))&& ((dest->brithday[1] <= '9')&&(dest->brithday[1] >= '0'))&& ((dest->brithday[2] <= '9')&&(dest->brithday[2] >= '0'))&& ((dest->brithday[3] <= '9')&&(dest->brithday[3] >= '0'))&& (dest->brithday[4] == '-')&&((dest->brithday[5] <= '1')&&(dest->brithday[5] >= '0'))&&((dest->brithday[6] <= '9')&&(dest->brithday[6] >= '0'))&&(dest->brithday[7] == '-')&&((dest->brithday[8] <= '3')&&(dest->brithday[8] >= '0'))&&((dest->brithday[9] <= '9')&&(dest->brithday[9] >= '0')))
{
if(dest->brithday[5] == '1')
{
if(dest->brithday[6] <= '2')
{
;
}
else
{
goto loop;
}
}
if(dest->brithday[8] == '3')
{
if(dest->brithday[9] <= '1')
{
;
}
else
{
goto loop;
}
}
break; /*合法结束*/
}
else
{
loop:
printf("输入有误!\n");
printf("您输入的数据必须为XXXX-XX-XX的格式\n");
}
}
while(1) /*判断输入是否合法*/
{
printf("请输入你要添加的电话:");
scanf("%s",dest->tele);
if((strlen(dest->tele) == 11)&&((dest->tele[0] <= '9')&&(dest->tele[0] >= '0'))&&((dest->tele[1] <= '9')&&(dest->tele[1] >= '0'))&&((dest->tele[2] <= '9')&&(dest->tele[2] >= '0'))&&((dest->tele[3] <= '9')&&(dest->tele[3] >= '0'))&&((dest->tele[4] <= '9')&&(dest->tele[4] >= '0'))&&((dest->tele[5] <= '9')&&(dest->tele[5] >= '0'))&&((dest->tele[6] < '9')&&(dest->tele[6] >= '0'))&&((dest->tele[7] <= '9')&&(dest->tele[7] >= '0'))&&((dest->tele[8] <= '9')&&(dest->tele[8] >= '0'))&&((dest->tele[9] <= '9')&&(dest->tele[9] >= '0'))&&((dest->tele[10] <= '9')&&(dest->tele[10] >= '0')))
{
break; /*合法结束*/
}
else
{
printf("输入有误!\n");
printf("您输入的数据必须为11位数字!\n");
}
}
}
/**********************************************************************************
* 赋值函数(初始化时使用)
*描述:该函数用于给结构体数据赋值。
*
*参数: TreeData *dest char *name char *studentID char *brithday char *tele
*
*返回值:无
*
*注意事项:方便赋值
**********************************************************************************/
void mycopy(TreeData *dest,char *name,char *studentID,char *brithday,char *tele)
{
strcpy(dest->name,name);
strcpy(dest->studentID,studentID);
strcpy(dest->brithday,brithday);
strcpy(dest->tele,tele);
}
/**********************************************************************************
* 寻找叶子结点函数
*描述:该函数用于寻找叶子结点。
*
*参数:TREENODE *root
*
*返回值:TREENODE
*
*注意事项:
**********************************************************************************/
TREENODE * findleaf(TREENODE *root)
{
static TREENODE * leaf = NULL;
if(root != NULL) /*root位NULL返回NULL*/
{
if((root->leftchild == NULL) && (root->rightchild == NULL)) /*左右孩子为空,返回当前结点*/
{
leaf = root;
return leaf;
}
findleaf(root->leftchild); /*递归调用左孩子*/
findleaf(root->rightchild); /*递归调用右孩子*/
}
return leaf;
}
/**********************************************************************************
* 查找父亲结点函数
*描述:该函数用于查找某一叶子结点的父结点。
*
*参数: TREENODE *root TREENODE *leaf
*
*返回值:TREENODE *
*
*注意事项:
**********************************************************************************/
TREENODE *findparent(TREENODE *root,TREENODE *leaf)
{
static TREENODE *parent = NULL;
if(root->leftchild != NULL) /*有左孩子*/
{
if(root->leftchild == leaf) /*判断左孩子是否为要找的孩子*/
{
parent = root;
}
else
{
findparent(root->leftchild,leaf); /*不是就递归调用左孩子*/
}
}
if(root->rightchild != NULL) /*有右孩子*/
{
if(root->rightchild == leaf) /*判断右孩子是否为要找的孩子*/
{
parent = root;
}
else
{
findparent(root->rightchild,leaf); /*不是就递归调用右孩子*/
}
}
return parent;
}
/**********************************************************************************
* 删除函数
*描述:该函数用于对指定姓名的结点进行删除。
*
*参数:TREENODE *root,char *info
*
*返回值:无
*
*注意事项:删除一个结点,将一个叶子结点拉上来,并删除叶子结点
**********************************************************************************/
void myremove(TREENODE *root,char *info)
{
TREENODE *find = (TREENODE *)malloc(sizeof(TREENODE));
TREENODE *leaf = (TREENODE *)malloc(sizeof(TREENODE));
TREENODE *parent = (TREENODE *)malloc(sizeof(TREENODE));
int ret = isfind(root,info); /*判断是否在树中*/
if(ret == 0)
{
printf("没有此人!\n");
}
else
{
find = mysearch(root,info); /*查找结点*/
printf("确定要删除此学生:\n");
printf("确定/取消?(Y/N):");
char yn;
setbuf(stdin,NULL); /*清输入缓存区*/
scanf("%c",&yn);
if(yn == 'Y')
{
leaf = findleaf(root); /*找到叶子结点*/
parent = findparent(root,leaf);/*找到叶子的父亲结点*/
if(leaf == find) /*要删除结点为叶子结点*/
{
free(find); /*直接删除*/
if(parent->leftchild == leaf)
{
parent->leftchild = NULL; /*将其父亲结点的对应指针置空*/
}
else
{
parent->rightchild = NULL;
}
find = NULL;
}
else
{
strcpy(find->stuinfo->name,leaf->stuinfo->name);
strcpy(find->stuinfo->studentID,leaf->stuinfo->studentID);
strcpy(find->stuinfo->brithday,leaf->stuinfo->brithday);
strcpy(find->stuinfo->tele,leaf->stuinfo->tele);
free(leaf); /*删除叶子*/
if(parent->leftchild == leaf)
{
parent->leftchild = NULL;
}
else
{
parent->rightchild = NULL;
}
leaf = NULL;
}
}
}
}
TREENODE * mycreatetree()
{
TREENODE *root = NULL;
return root;
}
/**********************************************************************************
* 添加函数
*描述:该函数用于添加学生。
*
*参数: TREENODE *root,TreeData *data
*
*返回值:无
*
*注意事项:
**********************************************************************************/
void myinsertnode(TREENODE *root,TreeData *data)
{
if(strcmp(root->stuinfo->studentID,data->studentID) < 0) /*插入左孩子*/
{
if(root->leftchild == NULL) /*左孩子为空直接插入*/
{
TREENODE *new = (TREENODE *)malloc(sizeof(TREENODE));
new->stuinfo = data;
new->leftchild = NULL;
new->rightchild = NULL;
root->leftchild = new;
}
else /*不为空递归调用*/
{
myinsertnode(root->leftchild,data);
}
}
else /*插入左孩子*/
{
if(root->rightchild == NULL) /*左孩子为空直接插入*/
{
TREENODE *new = (TREENODE *)malloc(sizeof(TREENODE));
new->stuinfo = data;
new->leftchild = NULL;
new->rightchild = NULL;
root->rightchild = new;
}
else /*不为空递归调用*/
{
myinsertnode(root->rightchild,data);
}
}
}
/**********************************************************************************
* 输出函数
*描述:该函数用于先跟遍历输出一颗二叉树。
*
*参数: TREENODE *root
*
*返回值:无
*
*注意事项:
**********************************************************************************/
void preorder(TREENODE *root)
{
if(root != NULL)
{
printf("姓名:%s\t学号:%s\t生日:%s\t电话:%s\n",root->stuinfo->name,root->stuinfo->studentID,root->stuinfo->brithday,root->stuinfo->tele);
preorder(root->leftchild);
preorder(root->rightchild);
}
}
/**********************************************************************************
* 查找函数
*描述:该函数用于查找指定姓名的结点是否在树中。
*
*参数: TREENODE *root char *info
*
*返回值:int
*
*注意事项:
**********************************************************************************/
int isfind(TREENODE *root,char *info)
{
return ((root != NULL) && ((strcmp(root->stuinfo->name,info) == 0) || (isfind(root->leftchild,info) || isfind(root->rightchild,info))));
}
/**********************************************************************************
* 查找函数
*描述:该函数用于查找指定姓名的结点信息。
*
*参数: TREENODE *root char *info
*
*返回值:TREENODE *
*
*注意事项:
**********************************************************************************/
TREENODE * mysearch(TREENODE *root,char *info)
{
int ret = isfind(root,info);
static int flt = 0; /*第一次未找到置1,后面不在输出为找到*/
static TREENODE *find = NULL;
if((ret == 0) && (flt == 0))
{
printf("系统为找到此人!\n");
return;
}
else /*先根遍历查找此人*/
{
flt = 1;
if(root != NULL)
{
if(strcmp(root->stuinfo->name,info) == 0)
{
find = root;
printf("姓名:%s\t学号:%s\t生日:%s\t电话:%s\n",root->stuinfo->name,root->stuinfo->studentID,root->stuinfo->brithday,root->stuinfo->tele);
return find;
}
mysearch(root->leftchild,info); /*递归调用左孩子*/
mysearch(root->rightchild,info); /*递归调用右孩子*/
}
}
return find;
}
/**********************************************************************************
* 修改函数
*描述:该函数用于对指定姓名结点的信息进行修该。
*
*参数: TREENODE *root,char *info
*
*返回值:int
*
*注意事项:
**********************************************************************************/
int mycorrect(TREENODE *root,char *info)
{
int ret = isfind(root,info);
static int flt = 0; /*第一次未找到置1,后面不在输出为找到*/
if((ret == 0) && (flt == 0))
{
printf("系统为找到此人!\n");
printf("请按Enter键继续...");
getchar();
getchar();
return; /*为找到结束函数*/
}
else
{
flt = 1;
if(root != NULL)
{
if(strcmp(root->stuinfo->name,info) == 0)
{
printf("姓名:%s\t学号:%s\t生日:%s\t电话:%s\n",root->stuinfo->name,root->stuinfo->studentID,root->stuinfo->brithday,root->stuinfo->tele);
printf("/**************************************/\n");
printf("/*************** 1.姓名 ***************/\n");
printf("/*************** 2.学号 ***************/\n");
printf("/*************** 3.生日 ***************/\n");
printf("/*************** 4.电话 ***************/\n");
printf("/*************** 5.取消 ***************/\n");
printf("/**************************************/\n");
int choose;
char yn;
char *buffer = (char *)malloc(sizeof(char));
printf("请输入你想修改的内容或按5取消修改:");
scanf("%d",&choose);
while((choose > 5) || (choose < 1))
{
printf("输入有误!\n");
printf("请重新输入要修改的内容或按5取消:");
scanf("%d",&choose);
}
switch(choose)
{
case 1:
{
printf("请输入要新的姓名:");
scanf("%s",buffer);
printf("您确定要将%s更改为%s吗?(Y/N):",root->stuinfo->name,buffer);
setbuf(stdin,NULL);
scanf("%c",&yn);
if(yn == 'Y')
{
strcpy(root->stuinfo->name,buffer);
printf("修改成功\n");
printf("请按Enter键继续...");
setbuf(stdin,NULL);
getchar();
getchar();
}
else
{
printf("数据没有修改!\n");
printf("请按Enter键继续...");
setbuf(stdin,NULL);
getchar();
getchar();
}
break;
}
case 2:
{
printf("请输入要新的学号:");
scanf("%s",buffer);
printf("您确定要将%s更改为%s吗?(Y/N):",root->stuinfo->studentID,buffer);
setbuf(stdin,NULL);
scanf("%c",&yn);
if(yn == 'Y')
{
strcpy(root->stuinfo->studentID,buffer);
printf("修改成功\n");
printf("请按Enter键继续...");
setbuf(stdin,NULL);
getchar();
getchar();
}
else
{
printf("数据没有修改!\n");
printf("请按Enter键继续...");
setbuf(stdin,NULL);
getchar();
getchar();
}
break;
}
case 3:
{
printf("请输入要新的生日:");
scanf("%s",buffer);
printf("您确定要将%s更改为%s吗?(Y/N):",root->stuinfo->brithday,buffer);
setbuf(stdin,NULL);
scanf("%c",&yn);
if(yn == 'Y')
{
strcpy(root->stuinfo->brithday,buffer);
printf("修改成功\n");
printf("请按Enter键继续...");
setbuf(stdin,NULL);
getchar();
getchar();
}
else
{
printf("数据没有修改!\n");
printf("请按Enter键继续...");
setbuf(stdin,NULL);
getchar();
getchar();
}
break;
}
case 4:
{
printf("请输入要新的电话:");
scanf("%s",buffer);
printf("您确定要将%s更改为%s吗?(Y/N):",root->stuinfo->tele,buffer);
setbuf(stdin,NULL);
scanf("%c",&yn);
if(yn == 'Y')
{
strcpy(root->stuinfo->tele,buffer);
printf("修改成功\n");
printf("请按Enter键继续...");
getchar();
getchar();
}
else
{
printf("数据没有修改!\n");
printf("请按Enter键继续...");
setbuf(stdin,NULL);
getchar();
getchar();
}
break;
}
case 5:
{
break;
}
}//switend
goto end;
} //if==end
mycorrect(root->leftchild,info);
mycorrect(root->rightchild,info);
} // if==NULLend
} //else end
end:
return;
}
/**********************************************************************************
* 菜单函数
*描述:该函数用于对屏幕进行初始化。
*
*参数:TREENODE *root
*
*返回值:无
*
*注意事项:
**********************************************************************************/
void display(TREENODE *root)
{
int choose;
system("clear");
printf("\n\n\n\n\n\n\n\n\n\n\n");
printf("\t\t\t 欢迎使用通讯录管理系统!\n");
printf("\n\n\n\n\n\n\n\n\n\n\n");
sleep(2);
system("clear");
while(1)
{
system("clear");
printf("/************通讯录管理系统************/\n");
printf("/*************** 1.查看 ***************/\n");
printf("/*************** 2.修改 ***************/\n");
printf("/*************** 3.添加 ***************/\n");
printf("/*************** 4.查找 ***************/\n");
printf("/*************** 5.删除 ***************/\n");
printf("/*************** 6.退出 ***************/\n");
printf("/**************************************/\n");
printf("请输入您的选择(1-6):");
scanf("%d",&choose);
if((choose > 6) || (choose < 1)) /*判断输入是否合法*/
{
printf("输入有误,您的选择必须在1-5之间!\n");
printf("请重新输入:");
scanf("%d",&choose);
}
switch(choose)
{
case 1:
{
system("clear"); /*清屏*/
preorder(root);
printf("请按Enter键继续...");
setbuf(stdin,NULL);
getchar();
break;
}
case 2:
{
system("clear"); /*清屏*/
char *info = (char *)malloc(sizeof(char));
printf("请输入要修改的人的姓名:");
scanf("%s",info);
mycorrect(root,info);
break;
}
case 3:
{
system("clear"); /*清屏*/
TreeData *info = (TreeData *)malloc(sizeof(TreeData));
myeva(info);
printf("您确定要添加学生:\n");
printf("姓名:%s\t学号:%s\t生日:%s\t电话:%s\n",info->name,info->studentID,info->brithday,info->tele);
printf("确定/取消(Y/N)?");
char yn;
setbuf(stdin,NULL);
scanf("%c",&yn);
if(yn == 'Y')
{
if(root == NULL)
{
root = (TREENODE *)malloc(sizeof(TREENODE));
root->stuinfo = info;
root->leftchild = NULL;
root->rightchild = NULL;
}
else
{
myinsertnode(root,info);
}
printf("添加成功!\n");
}
else
{
printf("取消添加!\n");
}
printf("请按Enter键继续...");
getchar();
getchar();
break;
}
case 4:
{
system("clear"); /*清屏*/
char *info = (char *)malloc(sizeof(char));
printf("请输入要查找的人的姓名:");
scanf("%s",info);
mysearch(root,info);
printf("请按Enter键继续...");
setbuf(stdin,NULL);
getchar();
break;
}
case 5:
{
system("clear"); /*清屏*/
char *info = (char *)malloc(sizeof(char));
printf("请输入要删除的人的姓名:");
scanf("%s",info);
myremove(root,info);
printf("请按Enter键继续...");
getchar();
getchar();
break;
}
case 6:
{
system("clear"); /*清屏*/
printf("\n\n\n\n\n\n\n\n\n\n\n");
printf("\t\t\t\t欢迎再次使用!\n");
printf("\n\n\n\n\n\n\n\n\n\n\n");
sleep(2);
system("clear");
exit(0);
}
default:
{
;
}
}
}
}
/**********************************************************************************
* 菜单函数
*描述:该函数用于对屏幕进行初始化。
*
*参数:TREENODE *root
*
*返回值:无
*
*注意事项:
**********************************************************************************/
TREENODE * treeinit(TREENODE *root)
{
TreeData * info[4]; /*初始化四个人,题目要求*/
int i;
for(i = 0; i < 4; i++)
{
if((info[i] = (TreeData *)malloc(sizeof(TreeData))) == NULL)
{
printf("分配空间失败!\n");
}
}
mycopy(info[0],"张一","202090116","1990-10-11","15298377000");
mycopy(info[1],"张二","202090114","1990-10-12","15298377111");
mycopy(info[2],"张三","202090115","1990-10-13","15298377222");
mycopy(info[3],"张四","202090118","1990-10-14","15298377333");
root = (TREENODE *)malloc(sizeof(TREENODE));
root->stuinfo = info[0];
root->leftchild = NULL;
root->rightchild = NULL;
myinsertnode(root,info[1]);
myinsertnode(root,info[2]);
myinsertnode(root,info[3]);
return root;
}
/**********************************************************************************
* 主函数
*描述:主函数
*
*参数:无
*
*返回值:int
*
*注意事项:
**********************************************************************************/
int main()
{
TREENODE * root = NULL;
root = mycreatetree();
root = treeinit(root);
display(root);
return 0;
}