实验报告
实验题目:二叉树
实验目的:
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的左节点
(层次遍历)

结果与讨论:
程序完成情况较好,由于实验内容比较多,所以写了很多函数,但有些函数之间是有调用关系,减轻了工作量。同时利用循环菜单也让程序看起来更为简洁,调用子程序也更为方便。

程序代码:

include

include

include

include

define OK 1

define ERROR 0

//先序遍历建立二叉树 
 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);

    }

}
}