二叉排序树与文件的操作(C、C++)
2017-07-10 11:03
197 查看
/* 功能要求: (1)从键盘输入一组学生记录建立二叉排序树; (2)二叉排序树存盘; (3)由文件恢复内存的二叉排序树; (4)中序遍历二叉排序树; (5)求二叉排序树深度; (6)求二叉排序树的所有节点数和叶子节点数; (7)向二叉排序树插入一条学生记录; (8)从二叉排序树中删除一条学生记录; (9)从二叉排序树中查询一条学生记录; (10)以广义表的形式输出二叉排序树 等功能。 注:第十个广义表我没做,不会T_T */ #include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <iomanip> #include <fstream> #include <math.h> using namespace std; int sum; //定义学生记录类型 struct student { char num[20];//学号 int grade;//成绩 }; //定义二叉排序树节点值的类型为学生记录类型 typedef struct student ElemType; //定义二叉排序树的节点类型 typedef struct bnode { ElemType data; struct bnode *lchild; struct bnode *rchild; }BNode,*BiTree; /*在根指针T所指的二叉排序树中递归地查找某关键字为key的数据元素, 如果查找成功,则指针p只想该数据元素结点并返回1,否则p指向查找路 径上访问的最后一个结点并返回0,指针f指向T的双亲,初值为NULL。*/ int searchBST(BiTree T,ElemType key,BiTree f,BiTree &p) { if(!T) //如果根指针为空,即查找失败,p置空,返回0 { p=f; return 0; } else if(strcmp(key.num,T->data.num)==0&&key.grade==T->data.grade) //如果根指针所指结点的值就是要查找的值,p就等于T,返回1 { p=T; return 1; } else if(key.grade<T->data.grade) //如果要查的值比根节点小,就到T的左子树去找 return searchBST(T->lchild,key,T,p); else return searchBST(T->rchild,key,T,p); //如果要查的值比根节点大,就到T的左子树去找 } /*当二叉排序树T中不存在关键字e时,插入e并返回1,否则返回0*/ int InsertBST(BiTree &T,ElemType e) { BiTree p,s; //p为查找关键字e路径上最后一个结点的指针,或者是指向关键字e的指针 //s为插入新结点所需要开辟的空间首地址 if(!searchBST(T,e,NULL,p)) //如果查找失败,说明要进行插入操作 { s=(BiTree)malloc(sizeof(BNode)); s->data.grade=e.grade; strcpy(s->data.num,e.num); s->lchild=s->rchild=NULL; //s肯定是没有孩子的 if(!p) //如果p为空,说明T就是一颗空树,直接让s当根就好了 T=s; else if(e.grade<p->data.grade) //如果e比p->data小,说明要插到p的左子树上 p->lchild=s; else if(e.grade>p->data.grade) //如果e比p->data大,说明要插到p的右子树上 p->rchild=s; return 1; } else //说明查找成功!那么就没有插入的必要了,直接返回0即可 return 0; } void inorder(BiTree bt) { if(bt) { inorder(bt->lchild); printf("学号:%s 成绩:%d\n",bt->data.num,bt->data.grade); inorder(bt->rchild); } } int Depth(BiTree bt) { int depthval,depthleft,depthright; if(!bt) depthval=0; else { depthleft=Depth(bt->lchild); depthright=Depth(bt->rchild); depthval=1+(depthleft>depthright?depthleft:depthright); } return depthval; } void count_all_nodes(BiTree bt,int &count) { if(bt) { count++; c720 count_all_nodes(bt->lchild,count); count_all_nodes(bt->rchild,count); } } void count_all_leaves(BiTree bt,int &count) { if(bt) { if(bt->lchild==NULL&&bt->rchild==NULL) count++; count_all_leaves(bt->lchild,count); count_all_leaves(bt->rchild,count); } } int Delete(BiTree &p) { BiTree q,s; if(!p->rchild) { q=p; p=p->lchild; free(q); } else if(!p->lchild) { q=p; p=p->rchild; free(q); } else { q=p; s=p->lchild; while(s->rchild) { q=s; s=s->rchild; } p->data=s->data; if(q!=p) q->rchild=s->lchild; else q->lchild=s->lchild; free(s); } return 1; } int DeleteBST(BiTree &T,ElemType key) { if(!T) return 0; else { if(key.grade==T->data.grade&&strcmp(key.num,T->data.num)==0) return Delete(T); else if(key.grade<T->data.grade) return DeleteBST(T->lchild,key); else return DeleteBST(T->rchild,key); } } void inorder_save(BiTree bt,char num[][20],int grade[10]) { static int x=0; if(bt) { strcpy(num[x],bt->data.num); grade[x]=bt->data.grade; x++; inorder_save(bt->lchild,num,grade); inorder_save(bt->rchild,num,grade); } } void menu() { printf("\n1.从键盘输入一组学生记录建立二叉排序树并存盘\n"); printf("2.二叉排序树存盘\n"); printf("3.由文件恢复内存的二叉排序树\n"); printf("4.中序遍历二叉排序树\n"); printf("5.求二叉排序树深度\n"); printf("6.求二叉排序树的所有节点数和叶子节点数\n"); printf("7.向二叉排序树插入一条学生记录\n"); printf("8.从二叉排序树中删除一条学生记录\n"); printf("9.从二叉排序树中查询一条学生记录\n"); printf("10.以广义表的形式输出二叉排序树\n"); printf("11.退出系统\n"); } BiTree search_num(BiTree bt,char nu[]) //通过生日找到结点并返回 { BiTree l_result,r_result; if(!bt) return NULL; if(strcmp(bt->data.num,nu)==0) return bt; else { l_result=search_num(bt->lchild,nu); r_result=search_num(bt->rchild,nu); return l_result?l_result:(r_result?r_result:NULL); } } int main() { int n,i,k,m,grade[10],depthval,count1,count2; ElemType stu[20],st; char str[20],nu[20],num[20][20]; BiTree bt=NULL,p; printf("欢迎来到二叉排序树管理系统!\n"); LL1:menu(); printf("\n请输入你的选择:\n"); scanf("%d",&m); switch(m) { case 1: { printf("请输入学生的个数:\n"); scanf("%d",&n); sum=n; printf("请输入%d个学生的学号和成绩,中间用空格隔开:\n",n); ofstream fout("bst.txt"); memset(num,0,sizeof(num)); for(i=0;i<sum;i++) { scanf("%s%d",stu[i].num,&stu[i].grade); fout<<stu[i].num<<" "<<stu[i].grade<<endl; strcpy(num[i],stu[i].num); grade[i]=stu[i].grade; InsertBST(bt,stu[i]); } goto LL1; break; } case 2: { ofstream fout("bst.txt"); inorder_save(bt,num,grade); for(i=0;i<sum;i++) fout<<num[i]<<" "<<grade[i]<<endl; fout.close(); printf("从文件读取的结果为:\n"); ifstream fin("bst.txt"); for(i=0;i<sum;i++) { fin>>str>>k; cout<<str<<" "<<k<<endl; } fin.close(); goto LL1; break; } case 3: { bt=NULL; ifstream fin("bst.txt"); printf("请输入学生的个数:\n"); scanf("%d",&sum); printf("文件里的内容为:\n"); for(i=0;i<sum;i++) { fin>>str>>k; strcpy(st.num,str); st.grade=k; printf("学号:%s 成绩:%d\n",st.num,st.grade); InsertBST(bt,st); } printf("\n二叉排序树的中序遍历为:\n"); inorder(bt); goto LL1; break; } case 4: { printf("二叉排序树的中序遍历为:\n"); inorder(bt); goto LL1; break; } case 5: { depthval=Depth(bt); if(depthval) printf("二叉排序树的深度为:%d\n",depthval); else printf("二叉排序树为空!\n"); goto LL1; break; } case 6: { count1=count2=0; count_all_nodes(bt,count1); count_all_leaves(bt,count2); printf("二叉排序树中所有结点个数为:%d\n",count1); printf("二叉排序树中所有叶子结点个数为:%d\n",count2); goto LL1; break; } case 7: { printf("请输入新增学生的个数:\n"); scanf("%d",&n); sum+=n; printf("请输入%d个学生的学号和成绩,中间用空格隔开:\n",n); for(i=0;i<n;i++) { scanf("%s%d",stu[i].num,&stu[i].grade); InsertBST(bt,stu[i]); } printf("二叉排序树的中序遍历为:\n"); inorder(bt); goto LL1; break; } case 8: { sum--; printf("请输入你想删除的那个人的学号和成绩:\n"); scanf("%s%d",st.num,&st.grade); DeleteBST(bt,st); printf("二叉排序树的中序遍历为:\n"); inorder(bt); goto LL1; break; } case 9: { printf("请输入你想查找的学号\n"); scanf("%s",nu); p=search_num(bt,nu); if(!p) printf("error!\n"); printf("你查找的这个人的信息为:\n"); printf("学号:%s\n",p->data.num); printf("分数:%d\n",p->data.grade); goto LL1; break; } case 10: { goto LL1; break; } case 11: { printf("谢谢你的使用,寨见!\n"); exit(0); } default: { printf("你的输入有误,请重新输入!\n"); goto LL1; break; } } }
相关文章推荐
- Perl的文件操作(2)(适合初学者)
- 在VC中自建操作BMP位图文件的类
- 在ASP.NET中操作文件的例子(VB)
- 操作ini文件
- Java中对文件的操作
- java文件操作
- 如何在asp.net中操作文件
- ASP.net中上传文件的操作
- ASP.net中上传文件的操作
- SMTH Java FAQ (3) 文件与磁盘操作(菜鸟必看)
- .net入门之VB篇:Visual Basic.Net中的文件操作(一)
- 剖析VC中的文件操作
- 文件的操作
- 如何在linux下使用c语言操作临时文件
- Win32汇编教程十三 INI 文件的操作
- 在BCB下如何用ADO操作带密码的ACCESS文件?
- 使用java.io.*操作文件的拆分与合并,Application一例!
- Javascript----文件操作
- BMP位图文件结构及VC操作
- lotusscript操作word文件中的Class wordDate