实验报告
实验题目:二叉树
实验目的:
1、熟悉二叉树的结点类型和二叉树的基本操作。
2、掌握二叉树的前序、中序和后序遍历的算法。
3、加深对二叉树的理解,逐步培养解决实际问题的编程能力。
基本要求:
1.编写程序bitree.cpp实现ADTBiTree,要求使用二叉链表存储。实现基本操作:
InitBiTree(&T);
DestroyBiTree(&T);
PreOrder(T,visit());
InOrder(T,visit());
PostOrder(T,visit());
2.编码实现以下算法:
1)创建二叉树。(以先序扩展序列给出)
2)输出先序、中序和后序序列。
3)计算二叉树结点数、叶子结点数、高度。
测试数据:先序扩展序列:ABDF##G##E#H##C##输出:先序ABDFGEHC中序FDGBEHAC后序FGDHEBCA结点数:8叶子结点数:4高度:4。
实验拓展
1)实现层次遍历。
2)查找:查值为X的结点、双亲结点、孩子结点、兄弟结点
3)判断:判断一个二叉树是否为二叉排序树、完全二叉树、平衡和二叉树
4)处理:左右子树互换、复制、删除子树、插入子树
设计思路:
1. 在二叉树的存储结构为链式存储结构。
2. 在具体实现的时候建立不同函数,在主程序中用循环菜单的形式调用函数提高了效率。
概要分析:
二叉链表结构定义:
typedef struct BiNode{
ElemType data;
struct BiNode *lchild,*rchild;
}BiNode,*BiTree;
CreatBiTree(BiTree &T);先序建立二叉树。
DestroyBiTree(BiTree &T);销毁二叉树;
PreOrder(BiTree &T);先序遍历二叉树
InOrder(BiTree &T);中序遍历二叉树
PostOrder (BiTree &T);后序遍历二叉树
PrintbyLev(BiTree &T);按层次遍历二叉树,利用队列的思想,从根结点开始将其放入一个数组中,用i记录子节点尚未放入数组的位置,再将i所指向节点的左右节点放入队列中,然后i+1,对下一个节点这样操作,直至最后一个节点是叶子节点。
IsLeaf(BiTree &T);判断是否为叶子节点(是否有左右子树)。
FullBiTree(BiTree &T);判断是否为完全二叉树,采用广度优先遍历,从根节点开始,入队列,如果队列不为空,循环。遇到第一个没有左儿子或者右儿子的节点,设置标志位,如果之后再遇到有左/右儿子的节点,那么这不是一颗完全二叉树。
CountBiTree(BiTree &T);节点计数,用递归思想,对左右子树计数,再加起来。
LevelNum(BiTree& T,int t,int d);计算层数,利用递归思想,对左右子树计算层数并取较大值。
LeafNum(BiTree& T,int t,int d,int ln);叶子节点计数,利用递归思想,计算左右子树叶子再计算和。
Balance(BiTree &T,int i);判断是否为平衡二叉树,递归判断左右是否为平衡二叉树(有层数记录)。
Sort(BiTree &T,int i);判断是否为二叉排序树,判断此节点是否满足排序树定义,在判断其左右子树是否满足。
PrintChild(BiTree &T);打印左右子树。
FindNode(ElemType x,BiTree &T);查找算法,如果是根节点提示是根节点并返回指向根节点的指针,若果不是则调用Findx函数。
FindX(ElemType x,BiTree &temp,BiTree &T);查找算法,返回指向对应子树的根节点的指针。
CopyBiT(BiTree &T,BiTree &C);复制子树。
运行截图:
主界面
建立二叉树
输出三序遍历及二叉树信息
按层输出
查找二叉树
分析二叉树
左右子树互换:对A 然后按层次输出
删除以B为根节点的子树:
(层次遍历)
复制节点C
增加节点B于A的左节点
(层次遍历)
结果与讨论:
程序完成情况较好,由于实验内容比较多,所以写了很多函数,但有些函数之间是有调用关系,减轻了工作量。同时利用循环菜单也让程序看起来更为简洁,调用子程序也更为方便。
程序代码:
//先序遍历建立二叉树
Status CreatBiTree(BiTree &T){
ElemType c;
cin >> c;
if(c==’.’){
T=NULL;
}
else{
T=(BiNode*)malloc(sizeof(BiNode));
T->data=c;
CreatBiTree(T->lchild);
CreatBiTree(T->rchild);
}
return 1;
}
Status DestroyBiTree(BiTree &T){
if(!T) return 1;
else{
DestroyBiTree(T->lchild);
DestroyBiTree(T->rchild);
free(T);
T=NULL;
return 1;
}
}
Status PreOrder(BiTree &T){
if(T){
printf(“%c”,T->data);
if(PreOrder(T->lchild))
if(PreOrder(T->rchild)) return 1;
return 0;
}
else return 1;
}
Status InOrder(BiTree &T){
if(T){
InOrder(T->lchild);
printf(“%c”,T->data);
InOrder(T->rchild);
return 1;
}
else return 1;
}
Status PostOrder(BiTree &T){
if(T){
PostOrder(T->lchild);
PostOrder(T->rchild);
printf(“%c”,T->data);
}
return 1;
}
//按层输出
Status PrintbyLev(BiTree &T){
int i=0;
BiTree node[100];
int nn=1;
for(i=0;i<100;i++) node[i]=NULL;
node[0]=T;
i=0;
while(node[i]){
if(node[i]->lchild){
node[nn]=node[i]->lchild;
nn++;
}
if(node[i]->rchild){
node[nn]=node[i]->rchild;
nn++;
}
i++;
}
//CreatQueue(T);
for(i=0;node[i];i++){
printf(“%c”,node[i]->data);
}
printf(“\n”);
return 1;
}
int IsLeaf(BiTree &T){
if(T->lchild==NULL&&T->rchild==NULL) return 1;//叶子节点
else if(!T->lchild&&T->rchild) return 2;//有右无左
else if(!T->rchild&&T->lchild) return 3;//有左无右
else return 0; //有左有右
}
Status FullBiTree(BiTree &T){
int i=0,j=0;
BiTree node[100];
int nn=1;
for(i=0;i<100;i++) node[i]=NULL;
node[0]=T;
i=0;
while(node[i]){
if(node[i]->lchild){
node[nn]=node[i]->lchild;
nn++;
}
if(node[i]->rchild){
node[nn]=node[i]->rchild;
nn++;
}
i++;
}
i=0;
while(node[i]){
if(IsLeaf(node[i])==2) return 0;
i++;
}
while(IsLeaf(node[j])==0){
j++;
printf("*");
}
//j++;指针停在非左右子树都存在的节点的下一位
if(IsLeaf(node[j])==3||IsLeaf(node[j])==1) j++;
while(node[j]!=NULL){
if(IsLeaf(node[j])!=1) return 0;
j++;
printf("*");
}
return 1;
}
//计数
int CountBiTree(BiTree &T){
int m,n;
if(T){
m=CountBiTree(T->lchild);
n=CountBiTree(T->rchild );
return m+n+1;
}
else return 0;
}
//层数
int LevelNum(BiTree& T,int t,int d){
if(t>d) d=t;
if(!T) return 0;
if (T->lchild) {
d=LevelNum(T->lchild,t+1,d);
}
if (T->rchild) {
d=LevelNum(T->rchild,t+1,d);
}
return d;
}
//叶子节点计数
int LeafNum(BiTree& T,int t,int d,int ln){
if(t==d) ln++;
if(!T) return 0;
if (T->lchild) {
ln=LevelNum(T->lchild,t+1,ln);
}
if (T->rchild) {
ln=LevelNum(T->rchild,t+1,ln);
}
return ln;
}
//判断平衡
int Balance(BiTree &T,int i){
if (i==0) return i;
if (!T) return i;
if (abs(CountBiTree(T->lchild)-CountBiTree(T->rchild))>1){
i=0;return 0;
}
else {
Balance(T->lchild,i);
Balance(T->rchild,i);
}
return i;
}
//判断二叉排序树
int Sort(BiTree &T,int i){
if (i==0) return 0;
if(!T) return i;
if(T->lchild){
if (T->datalchild->data) return 0;
i=Sort(T->lchild,i);
}
else if (T->rchild){
if (T->datarchild->data) return 0;
i=Sort(T->rchild,i);
}
return i;
}
void judge(BiTree &T){
if(FullBiTree(T))
printf(“是完全二叉树\n”);
if(Balance(T,1))
printf(“是平衡二叉树\n”);
if(Sort(T,1))
printf(“是二叉排序树\n”);
}
//打印子树
void PrintChild(BiTree &T){
if(!T->lchild) printf(“此节点无左子树\n”);
else printf(“左子树为:%c\n”,T->lchild->data);
if(!T->rchild) printf(“此节点无右子树\n”);
else printf(“右子树为:%c\n”,T->rchild->data);
}
BiTree FindX(ElemType x,BiTree &temp,BiTree &T){
if (temp!=NULL||T==NULL) return temp;
if (T->lchild){
if (T->lchild->data==x)
return T;
else {
temp=FindX(x,temp,T->lchild);
temp=FindX(x,temp,T->rchild);
if(temp) return temp;
}
}
if (T->rchild){
//printf("**");
if (T->rchild->data==x)
return T;
else {
temp=FindX(x,temp,T->rchild);
temp=FindX(x,temp,T->lchild);
if(temp) return temp;
}
}
return temp;
}
//找X节点
BiTree FindNode(ElemType x,BiTree &T){
if(T->data==x){
printf("所找节点为根节点\n");
PrintChild(T);
return T;
}
BiTree Q=NULL;
Q=FindX(x,Q,T);
if(Q){
printf("其双亲节点为:%c\n",Q->data);
if(Q->lchild&&Q->lchild->data==x) {
if (!Q->rchild) printf("其无兄弟节点\n");
else printf("兄弟节点为%c\n",Q->rchild->data);
PrintChild(Q->lchild);
//return Q->lchild;
}
else{
if (!Q->lchild) printf("其无兄弟节点\n");
else printf("兄弟节点为%c\n",Q->lchild->data);
PrintChild(Q->rchild);
//return Q->rchild;
}
}
return Q;
}
//三序输出
void printBiTree(BiTree &T){
int d,Ln,n;
PreOrder(T);
printf(“\n”);
InOrder(T);
printf(“\n”);
PostOrder(T);
printf(“\n”);
n=CountBiTree(T);
printf(“节点数为:%d\n”,n);
d=LevelNum(T,1,1);
printf(“深度为:%d\n”,d);
Ln=LeafNum(T,1,d,0);
printf(“叶子节点个数为:%d\n”,Ln);
}
Status CopyBiT(BiTree &T,BiTree &C){
if(!T) C=NULL;
else{
C=(BiNode*)malloc(sizeof(BiNode));
C->data=T->data;
//C->lchild=T->lchild;
//C->rchild=T->rchild;
CopyBiT(T->lchild,C->lchild);
CopyBiT(T->rchild,C->rchild);
}
return 1;
}
int main()
{
BiTree T,x,temp,temp1;
int d,Ln,n,j=1;
ElemType c;
while(j){
printf(“1.建立二叉树\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”);
scanf(“%d”,&j);
switch(j){
case 1: CreatBiTree(T);break;
case 2: printBiTree(T);break;
case 3: PrintbyLev(T); break;
case 4:
printf(“请输入要查询节点:\n”);
getchar();
scanf(“%c”,&c);
x=FindNode(c,T);
break;
case 5:judge(T);break;
case 6:
printf(“输入根节点:\n”);
getchar();
scanf(“%c”,&c);
if(c==T->data){
x=T;
temp=x->lchild;
x->lchild=x->rchild;
x->rchild=temp;
PrintChild(T);
break;
}
x=FindNode(c,T);
if(x->lchild&&x->lchild->data==c){
x=x->lchild;
//x->lchild=NULL;
}
else if(x->rchild&&x->rchild->data==c) {
x=x->rchild;
// x->rchild=NULL;
}
temp=x->lchild;
x->lchild=x->rchild;
x->rchild=temp;
printf("交换之后:\n");
PrintChild(x);
break;
case 7:
printf("输入根节点:\n");
getchar();
scanf("%c",&c);
if(T->data==c){
x=T;
}
else{
x=FindNode(c,T);
}
if(x->lchild&&x->lchild->data==c){
temp=x->lchild;
x->lchild=NULL;
}
else if(x->rchild&&x->rchild->data==c) {
temp=x->rchild;
x->rchild=NULL;
}
//printBiTree(x);
DestroyBiTree(temp);
break;
//x=NULL;
case 8:
printf("输入根节点:\n");
getchar();
scanf("%c",&c);
x=FindNode(c,T);
if(x->lchild&&x->lchild->data==c){
temp=x->lchild;
}
else if(x->rchild&&x->rchild->data==c) {
temp=x->rchild;
// x->rchild=NULL;
}
CopyBiT(temp,temp1);
printBiTree(temp1);
break;
case 9:
printf("输入要插入的子树:\n");
CreatBiTree(temp1);
printf("输入插入根节点:\n");
getchar();
scanf("%c",&c);
if(T->data==c){
temp=T;
}
else{
x=FindNode(c,T);
if(x->lchild&&x->lchild->data==c){
temp=x->lchild;
}
else if(x->rchild&&x->rchild->data==c) {
temp=x->rchild;
}
}
printf("1.左子树 2.右子树\n");
scanf("%d",&d);
if(d==1) temp->lchild=temp1;
else temp->rchild=temp1;
//printBiTree(T);
}
}
}