#include"stdio.h"
#include"stdlib.h"
#include"string.h"
/****************************************************
copyright: self_chou
Filename: carpark.c
AUthour : self_chou Version: 1.0 Date: 2012.07
Description: 基于二叉排序树写的通讯录
Function List:
initdata() 初始化内置数据
insert() 添加联系人
find() 查找联系人
change() 修改联系人信息
delete() 删除联系人
destory() 释放空间
*******************************************************/
typedef struct student
{
char name[10];
char sno[10];
char bir[10];
char tel[10];
}student;
student class[50];
int current = 0;
int flag; //查找结果标记
typedef struct tree
{
struct student *people;
struct tree *left;
struct tree *right;
}tree;
tree *root = NULL;
void initdata() //内置的联系人
{
strcpy( class[current].name,"赵一");
strcpy( class[current].bir,"19910214");
strcpy( class[current].tel,"12345678");
strcpy( class[current].sno,"20125");
current++;
strcpy( class[current].name,"钱二");
strcpy( class[current].bir,"19900304");
strcpy( class[current].tel,"09876543");
strcpy( class[current].sno,"20126");
current++;
strcpy( class[current].name,"孙三");
strcpy( class[current].bir,"19910708");
strcpy( class[current].tel,"56780934");
strcpy( class[current].sno,"20127");
current++;
strcpy( class[current].name,"李四");
strcpy( class[current].bir,"19890506");
strcpy( class[current].tel,"09874532");
strcpy( class[current].sno,"20122");
root = (tree *)malloc(sizeof(tree));
root->people = &class[0];
root->left = NULL;
root->right = NULL;
}
void insert(tree * root,student *q) //排序二叉树按学号递归插入
{
flag = 0;
if(strcmp(root->people->sno,q->sno) == 0)
{
printf("插入不成功,相同学号的人已存在\n");
flag = 1;
return;
}
if( strcmp(root->people->sno,q->sno) > 0 )
{
if(root->left == NULL)
{
tree *p = (tree *)malloc(sizeof(tree));
p->people = q;
p->left = NULL;
p->right = NULL;
root->left = p;
}
else
{
insert(root->left,q);
}
}
else
{
if( root->right == NULL)
{
tree *p = (tree *)malloc(sizeof(tree));
p->people= q;
p->left = NULL;
p->right = NULL;
root->right = p;
}
else
{
insert(root->right,q);
}
}
}
int find(tree *root,char *p) //先跟遍历查找
{
int flag;
if( root!= NULL )
{
if( strcmp(root->people->name,p) == 0)
{
printf("已找到该联系人:\n");
printf("姓名:%s 学号:%s 生日:%s 电话:%s\n",root->people->name,root->people->sno,root->people->bir,root->people->tel);
return 1; //查找成功标记
}
flag = find(root->left,p);
if(flag>0)
{
return 1;
}
flag = find(root->right,p);
if(flag > 0)
{
return 1;
}
}
return 0;
}
int change(tree *root,char *p) //先根遍历,查找到后修改
{
int flag;
if(root != NULL)
{
if( strcmp(root->people->name,p) == 0)
{
int accept = 0;
char buff[20];
while(1)
{
if(accept == 5)
{
system("clear");
break;
}
printf("姓名:%s 学号:%s 生日:%s 电话:%s\n",root->people->name,root->people->sno,root->people->bir,root->people->tel);
printf("请输入要修改的选项:\n");
printf("1 修改姓名\n");
printf("2 修改学号\n");
printf("3 修改生日\n");
printf("4 修改电话\n");
printf("5 退出\n");
printf("请输入:");
scanf("%d",&accept);
switch(accept)
{
case 1:
{
system("clear");
printf("你想把名字修改为:");
scanf("%s",buff);
strcpy(root->people->name,buff);
printf("修改成功\n");
break;
}
case 2:
{
system("clear");
printf("你想把学号修改为(5位2012开头):");
scanf("%s",buff);
strcpy(root->people->sno,buff);
printf("修改成功\n");
break;
}
case 3:
{
system("clear");
printf("你想生日把修改为:");
scanf("%s",buff);
strcpy(root->people->bir,buff);
printf("修改成功\n");
break;
}
case 4:
{
system("clear");
printf("你想把电话修改为(8位):");
scanf("%s",buff);
strcpy(root->people->tel,buff);
printf("修改成功\n");
break;
}
case 5:
{
break;
}
default:
{
printf("输入有误,请重新输入\n");
break;
}
}
}
return 1;
}
flag = change(root->left,p);
if(flag >0 )
{
return 1;
}
flag = change(root->right,p);
if(flag >0)
{
return 1;
}
}
return 0;
}
void print(tree *root)
{
if(root != NULL)
{
printf("姓名:%s 学号:%s 生日:%s 电话:%s\n",root->people->name,root->people->sno,root->people->bir,root->people->tel);
print(root->left);
print(root->right);
}
}
tree * findparent(char *p,tree *root,tree *parent) //找寻待删除结点的父母结点
{
if( root != NULL)
{
if( strcmp(root->people->name,p) == 0 )
{
return parent; //和返回结点所在层次类似
}
parent = findparent(p,root->left,root);
if(parent != NULL)
{
return parent;
}
parent = findparent(p,root->right,root);
if(parent != NULL)
{
return parent;
}
}
return NULL;
}
void my_remove(tree *parent,tree *child) //删除结点
{
if(child->left == NULL && child->right == NULL) //叶子节点
{
tree *temp = child;
if(temp == root) //删除的是根
{
root = NULL;
free(temp);
return;
}
if(parent->left == child) //判断是父母的左孩子还是右孩子
{
parent->left = NULL;
}
else
{
parent->right = NULL;
}
free(temp);
}
else
{
if( child->left != NULL && child->right == NULL) //1度结点
{
if(parent == NULL) //删除的是根结点
{
root = root->left;
free(child);
return;
}
if( parent->left == child) //判断左右孩子,由其父母收养
{
parent->left = child->left;
}
else
{
parent->right = child->left;
}
free(child);
}
else
if( child->left == NULL && child->right != NULL)
{
if(parent == NULL)
{
root = root->right;
free(child);
return;
}
if( parent->left == child)
{
parent->left = child->right;
}
else
{
parent->right = child->right;
}
free(child);
}
else //二度结点
{
tree *temp,*temppar;
temp = child->right;
temppar = child;
while(temp->left != NULL) //找其中根遍历下的后继结点
{
temppar = temp;
temp = temp->left;
}
strcpy(child->people->name,temp->people->name);
strcpy(child->people->bir,temp->people->bir);
strcpy(child->people->tel,temp->people->tel);
strcpy(child->people->sno,temp->people->sno);
if( temppar == child) //后继结点为待删除结点右孩子
{ //注意这种情况
temppar->right = temp->right;
}
else
{
temppar->left = temp->right;
}
free(temp);
}
}
}
void delete(char *q)
{
tree *parent;
parent = findparent(q,root,NULL);
if( parent == NULL && ( strcmp( root->people->name,q) != 0 ))
{
printf("通讯录中没有此联系人,删除失败\n");
return;
}
if( parent == NULL) //删除分两步,先找到其父母结点,再
{ //分情况删除
my_remove(parent,root);
}
else
{
if( parent->left != NULL && (strcmp(parent->left->people->name,q) == 0 ) )
{
my_remove(parent,parent->left);
}
else
{
my_remove(parent,parent->right);
}
}
}
void destory(tree *root)
{
if(root != NULL) //释放空间
{
destory(root->left);
destory(root->right);
free(root);
}
}
void disp()
{
int fun;
char accept[20];
while(1)
{
printf("现有联系人按先序遍历如下:\n");
print(root);
printf(" 请输入要选择的功能\n");
printf("/************************************/\n");
printf(" 1.添加联系人\n");
printf(" 2.修改联系人信息\n");
printf(" 3.查找联系人\n");
printf(" 4.删除联系人\n");
printf(" 5.退出\n");
printf("/************************************/\n");
printf("请输入:");
scanf("%d",&fun);
switch(fun)
{
case 1:
{
system("clear");
if(root == NULL)
{
current++;
root = (tree *)malloc(sizeof(tree));
printf("请输入要添加的联系人姓名\n");
scanf("%s",accept);
strcpy(class[current].name,accept);
printf("请输入要添加联系人学号(5位:2012开头)\n");
scanf("%s",accept);
strcpy(class[current].sno,accept);
printf("请输入要添加的联系人生日\n");
scanf("%s",accept);
strcpy(class[current].bir,accept);
printf("请输入要添加的联系人电话(8位)\n");
scanf("%s",accept);
strcpy(class[current].tel,accept);
root->people = &class[current];
root->left = NULL;
root->right = NULL;
printf("添加完成\n");
break;
}
current++;
printf("请输入要添加的联系人姓名\n");
scanf("%s",accept);
strcpy(class[current].name,accept);
printf("请输入要添加的联系人学号(5位:2012开头)\n");
scanf("%s",accept);
strcpy(class[current].sno,accept);
printf("请输入要添加的联系人生日\n");
scanf("%s",accept);
strcpy(class[current].bir,accept);
printf("请输入要添加的联系人电话(8位)\n");
scanf("%s",accept);
strcpy(class[current].tel,accept);
insert(root,&class[current]);
if(flag == 1)
{
break;
}
printf("添加完成\n");
break;
}
case 2:
{
system("clear");
if(root == NULL)
{
printf("通讯录为空\n");
break;
}
printf("请输入要修改的联系人姓名:\n");
scanf("%s",accept);
fun = change(root,accept);
if(fun == 0)
{
printf("没有你要联系人\n");
}
break;
}
case 3:
{
system("clear");
if(root == NULL)
{
printf("通讯录为空\n");
break;
}
printf("请输入要查找的联系人姓名:\n");
scanf("%s",accept);
fun = find(root,accept);
if(fun == 0)
{
printf("联系人未找到\n");
}
break;
}
case 4:
{
system("clear");
if( root == NULL)
{
printf("通讯录为空\n");
break;
}
printf("请输入要删除的联系人姓名:");
scanf("%s",accept);
delete(accept);
break;
}
case 5:
{
system("clear");
printf("正在清除数据\n");
destory(root);
printf("欢迎使用本通讯录,seeyou!\n");
exit(0);
}
default:
{
system("clear");
printf("输入有误,请重新输入!\n");
break;
}
}
}
}
int main()
{
int i;
printf("正在初始化系统\n");
initdata();
for(i = 1;i <= current;i++)
{
insert(root,&class[i]);
}
disp();
return 0;
}