您的位置:首页 > 编程语言 > C语言/C++

二叉排序树与文件的操作(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;
}
}
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: