#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; }