功能要求:
(1)从键盘输入一组学生记录建立二叉排序树;
(2)*二叉排序树存盘;
(3)*由文件恢复内存的二叉排序树;
(4)中序遍历二叉排序树;
(5)求二叉排序树深度;
(6)求二叉排序树的所有节点数和叶子节点数;
(7)向二叉排序树插入一条学生记录;
(8)从二叉排序树中删除一条学生记录;
(9)从二叉排序树中查询一条学生记录;
(10)以广义表的形式输出二叉排序树
//定义学生记录类型
Struct student
{
Char num[6]; //学号
Int grade; //成绩
};
//定义二叉排序树节点值的类型为学生记录类型
typedef student ElemType;
//定义二叉排序树的节点类型
typedef Struct BSTNode
{
ElemType data;
Struct BSTNode *left;
Struct BSTNode *rchild;
} BSTNode;
#include
#define FN "D:\\BST.txt"
//二叉排序树
using namespace std;
typedef struct student
{
char num[6]; //学号
int grade; //成绩
} ElemType;
typedef struct BTnode
{
ElemType data;
BTnode *lchild,*rchild;
} BTnode,*BTtree;
ElemType a[105];
BTtree creatBTtree()
{
BTtree bt=NULL;
return bt;
}
int nodenum(BTtree T)//求结点数
{
int sum=0;
if(!T)
{
return 0;
}
else
{
sum=1+nodenum(T->lchild)+nodenum(T->rchild);
}
return sum;
}
int leafnodenum(BTtree T)//求结点数
{
int sum=0;
if(!T)
{
return 0;
}
else if((T->lchild==NULL)&&(T->rchild==NULL))
{
return 1;
}
else
{
return leafnodenum(T->lchild)+leafnodenum(T->rchild);
}
return sum;
}
void InOrderTraverseBTtree(BTtree T)//中序遍历
{
if(T)
{
InOrderTraverseBTtree(T->lchild);
printf("学号:%s 成绩:%d\n",T->data.num,T->data.grade);
InOrderTraverseBTtree(T->rchild);
}
}
int Depth(BTtree T)
{
if(!T)return 0;
else
{
int m=Depth(T->lchild);
int n=Depth(T->rchild);
if(m>n){
return m+1;}
else{
return n+1;}
}
}
int SearchBST(BTtree T,char no[])//寻找元素是否存在
//T为当前根节点,e为要查找的元素,f为T的父节点,p为找到的元素节点或没找到时的根节点
{
queue<BTtree>q;
q.push(T);
while(!q.empty())
{
BTtree t=q.front();
q.pop();
if (strcmp((t->data.num),no)==0)
{
return t->data.grade;
}
if (t->lchild)
{
q.push(t->lchild);
}
if (t->rchild)
{
q.push(t->rchild);
}
}
return 0;
}
int InsertBST(BTtree &T,char no[],int e)//插入函数
{
BTtree s=NULL,p,q=NULL;
s=new BTnode;
strcpy(s->data.num,no);
s->data.grade=e;
s->lchild=s->rchild=NULL;
if(!T)//若树空
{
T=s;
return 1;
}
if(SearchBST(T,no))//如果该元素已在树中
{
return 0;
}
p=T;
while(p)
{
q=p;
if(p->data.grade > e)//如果该元素比根节点值小
{
p=p->lchild;
}
else//如果该元素比根节点值大
{
p=p->rchild;
}
}
if(q->data.grade>e)
{
q->lchild=s;
return 1;
}
else
{
q->rchild=s;
return 1;
}
return 0;
}
int Delete(BTtree *p)//删除函数的具体操作
{
BTtree q,s;
if((*p)->rchild==NULL)//缺右子树
{
q=*p;
*p=(*p)->lchild;//用左子女替代
free(q);
}
else if((*p)->lchild==NULL)//缺左子树
{
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(*p!=q)
{
q->rchild=s->lchild;
}
else
{
q->lchild=s->lchild;
}
free(s);
}
return 1;
}
int DeleteBST(BTtree *T,int e)//删除函数
{
if(!*T)
{
return -1;
}
else
{
if((*T)->data.grade==e)
{
return Delete(T);
}
else if(e<(*T)->data.grade)
{
return DeleteBST(&(*T)->lchild,e);
}
else
{
return DeleteBST(&(*T)->rchild,e);
}
}
}
int f_write(BTtree T)
{
FILE *fp;
if((fp=fopen(FN,"w+"))==NULL)
{
printf("fail open!\n");
return -1;
}
queue<BTtree>q;
q.push(T);
while(!q.empty())
{
BTtree t=q.front();
q.pop();
fprintf(fp,"%s %d\n",t->data.num,t->data.grade);
printf("%s %d\n",t->data.num,t->data.grade);
if (t->lchild)
{
q.push(t->lchild);
}
if (t->rchild)
{
q.push(t->rchild);
}
}
cout<<"文件存储成功!"<<endl;
fclose(fp);
return 0;
}
int f_read(BTtree &T)
{
FILE *fp;
if((fp=fopen(FN,"r+"))==NULL)
{
printf("fail open!\n");
return -1;
}
int x;
char str[6];
while (!feof(fp))
{
fscanf(fp,"%s %d\n",str,&x);
//str[6]='\0';
InsertBST(T,str,x);
}
cout<<"文件打开成功!"<<endl;
fclose(fp);
return 0;
}
void Put(BTtree T)//以广义表形式输出
{
if(T!=NULL)
{
//cout<<"(";
cout<<T->data.num;
if(T->lchild!=NULL||T->rchild!=NULL)
{
cout<<"(";
Put(T->lchild);
if(T->rchild!=NULL)
{
cout<<",";
}
Put(T->rchild);
cout<<")";
}
}
}
/*
二叉树的广义表示形式:
a:表示根节点为a,左右节点均为空
a(b):表示根节点为a,左节点为b,右节点为空
a(,c):表示根节点为a,左节点为空,右节点为c
a(b,c)表示父节点为a,左子节点与右子节点分别为b和c
*/
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\n");
}
int main()
{
printf("--------二叉排序树存储学生信息系统--------\n");
BTtree T;
T=creatBTtree();
int ch;
while (1)
{
menu();
printf("请输入操作序号:\n");
cin>>ch;
switch(ch)
{
case 1:
int n;
ElemType x;
printf("请输入你要记录的学生信息个数:");
cin>>n;
for(int i=1; i<=n; i++)
{
printf("请输入你要记录的学生信息:");
cin>>x.num>>x.grade;
InsertBST(T,x.num,x.grade);
}
break;
case 2:
f_write(T);
break;
case 3:
f_read(T);
break;
case 4:
printf("\n中序遍历该二叉排序树的结果为:\n");
InOrderTraverseBTtree(T);
break;
case 5:
printf("\n二叉树深度为:%d\n",Depth(T));
break;
case 6:
printf("\n二叉树结点数为:%d\n",nodenum(T));
printf("\n二叉树叶子结点数为:%d\n",leafnodenum(T));
break;
case 7:
char s[6];
int score;
printf ("请输入插入学生学号\n");
cin>>s;
if(SearchBST(T,s))
{
printf("该学生信息已经存在,无法进行插入操作!\n");
break;
}
printf ("请输入插入学生成绩\n");
cin>>score;
InsertBST(T,s,score);
printf ("进行插入操作后的学生信息为\n");
InOrderTraverseBTtree(T);
break;
case 8:
printf ("请输入删除学生学号\n");
char Del[6];
cin>>Del;
if(!SearchBST(T,Del))
{
printf("该数不存在,无法进行删除操作!\n");
}
else
{
DeleteBST(&T,SearchBST(T,Del));
printf ("进行删除操作后的学生信息为\n");
InOrderTraverseBTtree(T);
}
break;
case 9:
printf ("请输入查找学生学号\n");
char no[6];
cin>>no;
if(SearchBST(T,no))
{
printf ("学号为 %s 的同学成绩为 :%d\n",no,SearchBST(T,no));
}
else
{
printf("没有找到该学生\n");
}
break;
case 10:
printf("\n以广义表形式该二叉排序树的结果为:");
Put(T);
break;
default:
printf("输入序号有误,请重新输入\n");
break;
}
}
return 0;
}
/*
5
1901 98
1902 100
1903 87
1904 95
1905 65
*/