【王道数据结构课后习题练习完整版】5.3.3二叉树的遍历和线索二叉树

写在前面:以下为程序所用到的文件:

  • function.h头文件
//
// Created by 斋心 on 2023/7/2.
//

#ifndef INC_5_3_3_7_FUNCTION_H
#define INC_5_3_3_7_FUNCTION_H

#include<stdio.h>
#include<stdlib.h>

//二叉树结点结构体类型申明
typedef char BiElemType;
typedef struct BiNode{
    BiElemType c;
    struct BiNode *lchild,*rchild;
}BiNode,*BiTree;


typedef BiTree ElemType;
//创建二叉树辅助队列结构体类型申明
typedef struct tag{
    ElemType p;
    struct tag *pnext;
}tag_t,*ptag_t;

//层次遍历二叉树辅助队列结点结构体类型申明
typedef struct LinkNode{
    ElemType data;
    struct LinkNode *next;
}LinkNode;
//层次遍历辅助队列
typedef struct{
    LinkNode *front,*rear;
}LinkQueue;

//层次建树函数申明
BiTree CreateBiTree(BiTree &T);

//层次遍历辅助队列函数申明
void InitQueue(LinkQueue &Q);
void EnQueue(LinkQueue &Q,ElemType x);
bool DeQueue(LinkQueue &Q,ElemType &m);
bool IsEmpty(LinkQueue Q);

//二叉树遍历函数申明
void PreOrder(BiTree T);
void InOrder(BiTree T);
void PostOrder(BiTree T);
void LevelOrder(BiTree T);


//辅助栈结构体类型申明
typedef struct stack{
    ElemType data;
    struct stack *next;
}stack,*Lstack;


//辅助栈函数申明
void InitStack(Lstack &S);
void Push(Lstack &S,ElemType x);
void Pop(Lstack &S,ElemType &m);
bool IsEmpty(Lstack S);
void GetTop(Lstack S,ElemType &s);


#endif //INC_5_3_3_7_FUNCTION_H
  • CreateBiTree.cpp文件
//
// Created by 斋心 on 2023/7/2.
//

#include "function.h "

BiTree CreateBiTree(BiTree &T){
    T=NULL;
    BiElemType c;
    BiTree pnew;
    ptag_t phead=NULL,ptail=NULL,listnew,pcur;
    int tag=0;//标志孩子结点是否已经插入,防止连续插入空结点的情形
    while(scanf("%c",&c)){
        if(c=='\n'){
            break;
        }
        if(c=='0'){
            pnew=NULL;
            listnew=NULL;
        }else{
            pnew=(BiTree)calloc(1,sizeof(BiNode));
            pnew->c=c;
            listnew=(ptag_t)calloc(1,sizeof(tag_t));
            listnew->p=pnew;
        }
        if(NULL==T){
            phead=ptail=listnew;
            pcur=listnew;
            T=pnew;
        }else{
            if(listnew){
                ptail->pnext=listnew;
                ptail=listnew;
            }
            if(NULL==pcur->p->lchild&&tag!=1){
                pcur->p->lchild=pnew;
                tag=1;
            }else{
                pcur->p->rchild=pnew;
                pcur=pcur->pnext;
                tag=0;
            }
        }
    }
    return T;
}
  • queue.cpp文件
//
// Created by 斋心 on 2023/7/2.
//

#include"function.h"

void InitQueue(LinkQueue &Q){
    Q.front=Q.rear=(LinkNode *)calloc(1,sizeof(LinkNode));
}

void EnQueue(LinkQueue &Q,ElemType x){
    LinkNode *s=(LinkNode *)calloc(1,sizeof(LinkNode));
    s->data=x;
    Q.rear->next=s;
    Q.rear=s;
}

bool DeQueue(LinkQueue &Q,ElemType &m){
    if(Q.front==Q.rear){
        return false;
    }
    LinkNode *q=Q.front->next;
    m=q->data;
    Q.front->next=q->next;
    if(q==Q.rear){
        Q.rear=Q.front;
    }
    free(q);
    return true;
}

bool IsEmpty(LinkQueue Q){
    return Q.rear==Q.front;
}
  • order.cpp文件
//
// Created by 斋心 on 2023/7/2.
//

#include "function.h "
//前序遍历
void PreOrder(BiTree T){
    if(T){
        putchar(T->c);
        PreOrder(T->lchild);
        PreOrder(T->rchild);
    }
}


//中序遍历
void InOrder(BiTree p){
    if(p!=NULL){
        InOrder(p->lchild);
        printf("%c",p->c);
        InOrder(p->rchild);
    }
}

//后序遍历
void PostOrder(BiTree p){
    if(p!=NULL){
        PostOrder(p->lchild);
        PostOrder(p->rchild);
        printf("%c",p->c);
    }
}


//层序遍历
void LevelOrder(BiTree T){
    LinkQueue Q;//申请辅助队列
    InitQueue(Q);
    EnQueue(Q,T);//将树的根结点入队
    BiTree p;//存储出队的结点
    while(!IsEmpty(Q)){ //辅助队列非空,则将队头结点出队打印,并将其左孩子和右孩子依次入队
        DeQueue(Q,p);
        putchar(p->c);
        if(p->lchild){
            EnQueue(Q,p->lchild);
        }
        if(p->rchild){
            EnQueue(Q,p->rchild);
        }
    }
}
  • stack.cpp文件
//
// Created by 斋心 on 2023/7/2.
//

#include"function.h"
//带头结点的链栈初始化
void InitStack(Lstack &S){
    S=(Lstack)calloc(1,sizeof(stack));
}

//进栈(头插法)
void Push(Lstack &S,ElemType x){
    Lstack snew=(Lstack)calloc(1,sizeof(stack));
    snew->data=x;
    snew->next=S->next;
    S->next=snew;
}

//出栈(从头出栈)
void Pop(Lstack &S,ElemType &m){
    Lstack q=S->next;
    m=q->data;
    if(S->next!=NULL){   //栈不空,则出栈
        S->next=q->next;
    }
    free(q);
}

//判断栈空
bool IsEmpty(Lstack S){
    if(S->next==NULL){
        return 1;
    }
    return 0;
}

//读取栈顶元素
void GetTop(Lstack S,ElemType &s){
    if(S->next!=NULL){
        s=S->next->data;
    }
}

5.3.3-4 试给出二叉树自下而上,从右到左的层次遍历算法。

#include "function.h"

//5.3.3-4 试给出二叉树自下而上,从右到左的层次遍历算法。
//算法思想:二叉树层次遍历从上至下,从左到右依次访问结点,则将层次遍历输出的结点依次进栈,最后出栈,即可得到自下而上,自右向左的序列。

void RevLevelOrder(BiTree T){
    LinkQueue Q;
    InitQueue(Q);
    LinkStack S;
    InitStack(S);
    EnQueue(Q,T);//先将根结点入队
    while(!IsEmpty(Q)){ //队列非空,则将队头结点出队并入栈,然后如有左右孩子,则将左右孩子入队
        DeQueue(Q,T);
        Push(S,T);
        if(T->lchild){
            EnQueue(Q,T->lchild);
        }
        if(T->rchild){
            EnQueue(Q,T->rchild);
        }
    }
    while(!IsEmpty(S)){
        Pop(S,T);
        printf("%c",T->c);
    }
}



int main() {
    BiTree tree=NULL;
    CreateBiTree(tree);
    RevLevelOrder(tree);
    return 0;
}

输出结果:
abc0def0g
gfedcba
进程已结束,退出代码为 0

5.3.3-5 假设二叉树采用二叉链表存储结构,设计一个非递归算法求二叉树的高度。

#include "function.h"

//5.3.3-5 假设二叉树采用二叉链表存储结构,设计一个非递归算法求二叉树的高度。

//算法思想:用last指针指向当前层的最后一个结点,初始时是树根结点入队后队尾指针指向的结点。
//当层次遍历出队元素等于last变量时,则层高变量level加1,
//且last移动到下一层的最后一个结点,即为辅助队列尾指针所指的结点。

//求二叉树高度----非递归
int BtDepth(BiTree T){
    LinkQueue Q;
    InitQueue(Q);
    int level=0;//层高变量
    EnQueue(Q,T);
    BiTree last=Q.rear->data;//last初始值为树根结点
    while(!IsEmpty(Q)){
        DeQueue(Q,T);
        if(T->lchild){
            EnQueue(Q,T->lchild);
        }
        if(T->rchild){
            EnQueue(Q,T->rchild);
        }
        if(T==last){ //当出队元素等于last时,队列尾指针所指结点即为下一层的最后一个结点
            level++;
            last=Q.rear->data;
        }
    }
    return level;
}


//求二叉树高度---递归
int BtDepth2(BiTree T){
    if(T==NULL){
        return 0; //退出函数并返回0
    }
    int ldep=BtDepth2(T->lchild);
    int rdep=BtDepth2(T->rchild);
    if(ldep>rdep){
        return ldep+1;
    }else{
        return rdep+1;
    }
}


int main() {
    BiTree tree=NULL;
    CreateBiTree(tree);
    int level1,level2;
    level1=BtDepth(tree);
    level2= BtDepth2(tree);
    printf("the height of the bitree is:\n");
    printf("%3d%3d",level1,level2);
    return 0;
}

输出结果:
abcde
the height of the bitree is:
  3  3
进程已结束,退出代码为 0

5.3.3-6 设一颗二叉树中各结点的值互不相同,其先序遍历序列和中序遍历序列分别存于两个一维数组A[1…n]和B[1…n]中,试编写算法建立该二叉树的二叉链表。

#include <stdio.h>
#include<stdlib.h>


//设一颗二叉树中各结点的值互不相同,其先序遍历序列和中序遍历序列分别存于两个一维数组A[1...n]和B[1...n]中,试编写算法建立该二叉树的二叉链表。
//算法思想:先序序列和中序序列可以唯一确定一棵二叉树。① 根据先序序列确定树或子树的根结点;② 根据中序序列将树划分为左右子树。
// 采用递归算法,直到子树仅剩根结点为止。

typedef char BiElemType;
//二叉树结点的结构体类型申明
typedef struct BiNode{
    BiElemType c;
    struct BiNode *lchild,*rchild;
}BiNode,*BiTree;

//先序和中序序列创建二叉树
BiTree PreInCreate(char pre[],char in[],int pre1,int pren,int in1,int inn){
    //pre1和pren为先序序列的第一个和最后一个结点下标,in1和inn为中序序列的第一个和最后一个结点下标
    BiTree T=(BiTree)calloc(1,sizeof(BiNode));//申请子树根结点
    T->c=pre[pre1];//根结点为前序序列的第一个结点值
    //划分左右子树
    int i,llen,rlen;
    for(i=in1;T->c!=in[i];i++); //返回根结点所在中序序列的下标值
    llen=i-in1;//左子树中序序列长度
    rlen=inn-i;//右子树中序序列长度
    //递归创建左子树,退出接口左子树序列长为0
    if(llen){
        T->lchild=PreInCreate(pre,in,pre1+1,pre1+llen,in1,in1+llen-1);
    }else{
        T->lchild=NULL;
    }
   //递归创建右子树
   if(rlen){
       T->rchild= PreInCreate(pre,in,pren-rlen+1,pren,inn-rlen+1,inn);
   }else{
       T->rchild=NULL;
   }
   return T;
}


//先序遍历
void PreOrder(BiTree T){
    if(T){
        putchar(T->c);
        PreOrder(T->lchild);
        PreOrder(T->rchild);
    }
}


//中序遍历
void InOrder(BiTree T){
    if(T){
        InOrder(T->lchild);
        putchar(T->c);
        InOrder(T->rchild);
    }
}


int main() {
    char pre[6]="abdec";
    char in[6]="dbeac";
    BiTree T=PreInCreate(pre,in,0,4,0,4);
    printf("\n-------PreOrder---------\n");
    PreOrder(T);
    printf("\n--------InOrder----------\n");
    InOrder(T);
    return 0;
}

输出结果:
-------PreOrder---------
abdec
--------InOrder----------
dbeac
进程已结束,退出代码为 0

5.3.3-7 二叉树按二叉链表形式存储,写一个判别给定二叉树是否是完全二叉树的算法。

#include "function.h"

//二叉树按二叉链表形式存储,写一个判别给定二叉树是否是完全二叉树的算法。
//算法思想:具有n个结点的完全二叉树,其1-n号结点与满二叉树一一对应。可采用层次遍历的算法,将所有结点(包括空结点)加入队列。当出队遇到空节点时,
// 判断其后是否有非空结点,如有,则不是完全二叉树。


//判断是否为完全二叉树
bool IsComolete(BiTree T){
    LinkQueue Q;
    InitQueue(Q);
    EnQueue(Q,T);
    while(!IsEmpty(Q)){
        DeQueue(Q,T);
        if(T){ //此处与层次遍历不同,可让空的孩子也入队
            EnQueue(Q,T->lchild);
            EnQueue(Q,T->rchild);
        }else{

        }
        DeQueue(Q,T);
        if(T){
            return false;
        }
    }
    return true;
}



int main() {
    BiTree tree;
    CreateBiTree(tree);
    printf("\n-----LevelOrder----\n");
    LevelOrder(tree);
    bool ret= IsComolete(tree);
    printf("the bitree is complete:%d",ret);
    return 0;
}

输出结果:
abcd0e0

-----LevelOrder----
abcdethe bitree is complete:0
进程已结束,退出代码为 0

5.3.3-8 假设二叉树采用二叉链表存储结构存储,设计一个算法:计算一棵给定二叉树的所有双分支结点个数。

#include "function.h"

// 假设二叉树采用二叉链表存储结构存储,设计一个算法:计算一棵给定二叉树的所有双分支结点个数。
//算法思想:采用递归的思想。

//计算二叉树双分支结点数
int DouNode(BiTree T){
    if(T==NULL){  //递归出口,如结点无左右孩子,则返回0
        return 0;
    }
    if(T->lchild&&T->rchild){
        return DouNode(T->lchild)+ DouNode(T->rchild)+1; //二分支结点加1,且继续计算左右子树的二分支结点
    }else{
        return DouNode(T->lchild)+ DouNode(T->rchild);//继续计算左右子树的二分支结点
    }
}

int main() {
    BiTree tree;
    CreateBiTree(tree);
    int num= DouNode(tree);
    printf("the number of double node is:%d",num);
    return 0;
}

输出结果:
abcdef0g0
the number of double node is:2
进程已结束,退出代码为 0

5.3.3-9 设树B是一棵采用链式结构存储的二叉树,编写一个把树B中所有结点的左右子树进行交换的函数。

#include "function.h"

// 设树B是一棵采用链式结构存储的二叉树,编写一个把树B中所有结点的左右子树进行交换的函数。

void swap(BiTree T){
    if(T){
        swap(T->lchild);
        swap(T->rchild);
        BiTree p;
        p=T->lchild;
        T->lchild=T->rchild;
        T->rchild=p;
    }
}

int main() {
    BiTree tree;
    CreateBiTree(tree);
    printf("\n the bitree's levelorder is:\n");
    LevelOrder(tree);
    swap(tree);
    printf("\nthe swaped bitree's levelorder is:\n");
    LevelOrder(tree);
    return 0;
}

输出结果:
abcd0e0

 the bitree's levelorder is:
abcde
the swaped bitree's levelorder is:
acbed
进程已结束,退出代码为 0

5.3.3-10 假设二叉树采用二叉链表存储结构存储,设计一个算法:求先序遍历序列中第k个结点的值。

#include "function.h"

//  假设二叉树采用二叉链表存储结构存储,设计一个算法:求先序遍历序列中第k个结点的值。
//算法思想一:采用先序遍历非递归算法,设置变量j记录输出的先序序列结点数。
BiElemType PreNode1(BiTree T,int k){
    Lstack S;
    InitStack(S);
    BiTree p=T;
    int j=0;//记录访问的结点数
    while(p||!IsEmpty(S)){
        if(p){
            j++;
            if(j==k){
                return p->c;
            }
            Push(S,p);
            p=p->lchild;
        }else{
            Pop(S,p);
            if(p->rchild){
                p=p->rchild;
            }else{
                p=NULL;
            }
        }
    }
}


//算法思想二:采用递归算法。设置全局变量j表示遍历的前序序列结点数。按照前序递归遍历的思想:
// ①当结点为空时,返回特殊字符;
//② 当j==k时,返回结点值;
//③当k!=j时,则递归地在左子树和右子树中查找。

int j=1;//全局变量,前序遍历访问的结点数
BiElemType PreNode2(BiTree T,int k){
    if(T==NULL){
        return '#';
    }
    if(j==k){
        return T->c;
    }
    j++;
    BiElemType c= PreNode2(T->lchild,k);
    if(c!='#'){ //如左子树遍历完,尚未返回第k个的值,则会返回'#',需要在右子树继续遍历
        return c;
    }
    c= PreNode2(T->rchild,k);
    return c;
}



int main() {
    BiTree tree;
    CreateBiTree(tree);
    printf("\n the bitree's preorder is:");
    PreOrder(tree);
    BiElemType c1=PreNode1(tree,4);
    BiElemType c2= PreNode2(tree,4);
    printf("\n the %dth preorder1 node is: %c,the preorder2 node is:%c\n",4,c1,c2);
    return 0;
}

输出结果:
abcde00fg

 the bitree's preorder is:abdecfg
 the 4th preorder1 node is: e,the preorder2 node is:e

进程已结束,退出代码为 0

5.3.3-11 已知二叉树以二叉链表存储,编写算法完成:对于树中每个元素值为x的结点,删去以它为根的子树,并释放相应的空间。

#include "function.h"

//已知二叉树以二叉链表存储,编写算法完成:对于树中每个元素值为x的结点,删去以它为根的子树,并释放相应的空间。
//算法思想:本题分为两步:① 找到结点值为x的结点;② 递归地删除以x结点为根的子树。
//在查找结点x时,适合采用层次遍历算法;删除以x为结点的子树时,可采用后序遍历递归的思想。

//删除以T为根的子树
void DelTree(BiTree &T){ //沿着后序遍历的路径逐个删除子树结点
    if(T){
        DelTree(T->lchild);
        DelTree(T->rchild);
        free(T);
    }
}

//查找值为x的结点,并删除该结点的子树
void SearDelXTree(BiTree &T,BiElemType x){
    LinkQueue Q;
    InitQueue(Q);
    if(T->c==x){ //如树根结点的值为x,则直接删除整棵树
        DelTree(T);
        return;
    }
    EnQueue(Q,T);
    BiTree p;//遍历结点
    while(!IsEmpty(Q)){
        DeQueue(Q,p);
        if(p->lchild){
            if(p->lchild->c==x){
                DelTree(p->lchild);
                p->lchild=NULL;//删除后,p的左孩子为空
            }else{
                EnQueue(Q,p->lchild);
            }
            if(p->rchild){
                if(p->rchild->c==x){
                    DelTree(p->rchild);
                    p->rchild=NULL;
                }else{
                    EnQueue(Q,p->rchild);
                }
            }
        }
    }
}



int main() {
    BiTree tree;
    CreateBiTree(tree);
    printf("\n the tree's levelorder is:");
    LevelOrder(tree);
    SearDelXTree(tree,'a');
    printf("\n the new tree's levelorder is:");
    LevelOrder(tree);
    return 0;
}

输出结果:
tbcaef0cg

 the tree's levelorder is:tbcaefcg
 the new tree's levelorder is:tbcef
进程已结束,退出代码为 0

5.3.3-12 在二叉树中查找值为x的结点,编写算法打印值为x的结点的所有祖先结点,假设值为x的结点不多于一个。

#include "function.h"

//在二叉树中查找值为x的结点,编写算法打印值为x的结点的所有祖先结点,假设值为x的结点不多于一个。
//算法思想:非递归后序遍历栈中存放了从根结点到任一结点的路径,即可找到任一结点的所有祖先结点。

//打印值为x的结点的所有祖先结点
void SearXTree(BiTree T,BiElemType x){
    Lstack S;
    InitStack(S);
    BiTree p=T,r=NULL;
    while(p||!IsEmpty(S)){
        if(p){
            Push(S,p);
            p=p->lchild;
        }else{
            GetTop(S,p);
            if(p->rchild&&p->rchild!=r){
                p=p->rchild;
            }else{
                Pop(S,p);
                if(p->c==x){
                    printf("the anscestors of %c node are:\n",x);
                    while(!IsEmpty(S)){
                        Pop(S,p);
                        printf("%c",p->c);
                    }
                }
                r=p;
                p=NULL;
            }
        }
    }
}



int main() {
    BiTree tree;
    CreateBiTree(tree);
    printf("the tree's postorder is:\n");
    PostOrder(tree);
    printf("\n--------------------------\n");
    SearXTree(tree,'f');
}

输出结果:
the tree's postorder is:
hdebfgca
--------------------------
the anscestors of f node are:
ca
进程已结束,退出代码为 0

5.3.3-14 假设二叉树采用二叉链表存储结构,设计一个算法,求非空二叉树的宽度(即具有结点数最多的那一层的结点个数)。

#include "function.h"

//假设二叉树采用二叉链表存储结构,设计一个算法,求非空二叉树的宽度(即具有结点数最多的那一层的结点个数)。
//算法思想:采用层次遍历的思想。用rear标志二叉树每一层的最后一个结点,当出队元素p==rear时,此时队列尾指针指向的元素恰好是下一层的最后一个结点。


int TreeWidth(BiTree T){
    LinkQueue Q;
    InitQueue(Q);
    EnQueue(Q,T);
    BiTree rear=Q.rear->data;//标志每一层最后一个结点的指针
    BiTree p=NULL;//层次遍历指针
    int i=0,n=0;
    while(!IsEmpty(Q)){
        while(p!=rear){ //当出队元素p!=rear时,则持续层次遍历,并用i记录出队的结点数;当p==rear时,i恰好是该层的结点数
            DeQueue(Q,p);
            i++; //记录每一层的结点数量
            if(p->lchild){
                EnQueue(Q,p->lchild);
            }
            if(p->rchild){
                EnQueue(Q,p->rchild);
            }
        }
        rear=Q.rear->data;//当p==rear时,rear更新为指向下一层的最后结点
        if(n<=i){ //更新为结点数最多的那一层的结点个数
            n=i;
        }
        i=0; //重置i,记录下一层的结点数
    }
    return n;
}




int main() {
    BiTree tree;
    CreateBiTree(tree);
    printf("the tree's levelorder is:\n");
    LevelOrder(tree);
    int n= TreeWidth(tree);
    printf("\nthe width of tree is:%d",n);
}

输出结果:
abcd0e0fghi
the tree's levelorder is:
abcdefghi
the width of tree is:4
进程已结束,退出代码为 0

5.3.3-15 设有一棵满二叉树(所有结点值均不同),已知其先序序列为pre,设计一个算法求其后序序列post。

#include "function.h"

//设有一棵满二叉树(所有结点值均不同),已知其先序序列为pre,设计一个算法求其后序序列post。
//对于一棵满二叉树,任意一个结点的左、右子树均含有相等的结点数。同时,先序序列的第一个结点作为后序序列的最后一个结点。采用递归算法。

//满二叉树前序序列转换为后序序列
void PrePost(BiElemType pre[],int pre1,int pren,BiElemType post[],int post1,int postn){
    int half;
    if(pren>=pre1){
        post[postn]=pre[pre1];//后序序列的最后一个结点是先序序列的第一个结点
        half=(pren-pre1)/2;
        PrePost(pre,pre1+1,pre1+half,post,post1,post1+half-1);
        PrePost(pre,pre1+half+1,pren,post,post1+half,postn-1);
    }
}


int main() {
    char pre[8]="abdecfg";
    printf("pre is: %s\n",pre);
    char post[8];
    PrePost(pre,0,6,post,0,6);
    printf("post is: %s\n",post);
}

输出结果:
pre is: abdecfg
post is: debfgca

进程已结束,退出代码为 0

5.3.3-16 设计一个算法将二叉树的叶结点按从左到右的顺序连成一个单链表,表头指针为head,二叉树按二叉链表形式存储,链接时用叶结点的右指针来存放单链表指针。

#include "function.h"

//设计一个算法将二叉树的叶结点按从左到右的顺序连成一个单链表,表头指针为head,二叉树按二叉链表形式存储,链接时用叶结点的右指针来存放单链表指针。
//算法思想:二叉树先序中序和后序遍历的算法,对于叶子结点的访问都是从左到右。此处采用先序遍历的算法。设置指针pre,标志叶子结点的前驱指针。

BiTree head,pre=NULL;
BiTree Link(BiTree T){
    if(T){
        if(T->lchild==NULL&&T->rchild==NULL){
            if(pre==NULL){ //连接第一个叶子结点
                head=T;
                pre=T;
            }else{ //其它叶子结点
                pre->rchild=T;
                pre=T;
            }
        }
        Link(T->lchild);
        Link(T->rchild);
        pre->rchild=NULL;//处理最后一个结点
    }
    return head;
}


int main() {
    BiTree tree;
    CreateBiTree(tree);
    printf("preorder:\n");
    PreOrder(tree);
    printf("\nlink is:\n");
    Link(tree);
    PreOrder(head);
}

输出结果:
abc000f
preorder:
abcf
link is:
bf
进程已结束,退出代码为 0

5.3.3-17 试设计判断两棵二叉树是否相似的算法。所谓二叉树T1和T2相似,指的是T1和T2都是空的二叉树或都只有一个根结点;或T1的左子树和T2的右子树是相似的,且T1的右子树和T2的右子树是相似的。

#include "function.h"

//试设计判断两棵二叉树是否相似的算法。所谓二叉树T1和T2相似,指的是T1和T2都是空的二叉树或都只有一个根结点;
// 或T1的左子树和T2的右子树是相似的,且T1的右子树和T2的右子树是相似的。

//算法思想:采用递归的思想。如T1和T2均是空,则是相似的;如T1或T2一个空,一个非空,则是非相似的。然后递归比较其左右子树。
//1和T2都只有一个根结点的情况,可以包括在本递归算法中。

bool similar(BiTree T1,BiTree T2){
    bool retl,retr;
    if(T1==NULL&&T2==NULL){
        return true;
    }else if(T1==NULL||T2==NULL){
        return false;
    }
    retl=similar(T1->lchild,T2->lchild);
    retr= similar(T1->rchild,T2->rchild);
    return retl&&retr;
}



int main() {
    BiTree T1,T2;
    printf("input T1 nodes:\n");
    CreateBiTree(T1);
    printf("input T2 nodes:\n");
    CreateBiTree(T2);
    bool ret=similar(T1,T2);
    if(ret){
        printf("T1 and T2 is similar\n");
    }else{
        printf("T1 and T2 is not similar\n");
    }
}

输出结果:
input T1 nodes:
abc
input T2 nodes:
defg
T1 and T2 is not similar

进程已结束,退出代码为 0

5.3.3-19 计算二叉树的带权路径长度(WPL)。

#include "function.h"

//5.3.3-19 计算二叉树的带权路径长度(WPL)。
//算法思想:利用层次遍历算法计算树的带权路径长度。层次遍历算法可以获得各个结点所在的层次,如为叶子结点,则计算其带权路径长度。

int WPL_levelorder(BiTree T){
    LinkQueue Q;
    InitQueue(Q);
    EnQueue(Q,T);
    BiTree p;//遍历指针
    BiTree ptail=Q.rear->data;//每一层最后一个结点
    int level=0,wpl=0;
    while(!IsEmpty(Q)){
        DeQueue(Q,p);
        if(p->lchild){
            EnQueue(Q,p->lchild);
        }
        if(p->rchild){
            EnQueue(Q,p->rchild);
        }
        if(p->lchild==NULL&&p->rchild==NULL){ //如为叶子结点,则累加计算带权路径长度
           wpl+=p->weight*level;
        }
        if(p==ptail){ //如结点为该层最后一个结点,则层数加1,并将指针指向下一层最后一个结点
            level++;
            ptail=Q.rear->data;
        }
    }
    return wpl;
}



int main() {
    BiTree tree;
    CreateBiTree(tree);
    WeightOfNode(tree);
    printf("PreOrder:\n");
    PreOrder(tree);
    int wpl;
    wpl= WPL_levelorder(tree);
    printf("\nWPL of the tree is:%d",wpl);
}

输出结果:
abcd0ef
input weight:1
input weight:2
input weight:3
input weight:4
input weight:5
input weight:6
PreOrder:
a:1  b:2  d:3  c:4  e:5  f:6
WPL of the tree is:28
进程已结束,退出代码为 0

5.3.3-20 请设计一个算法,将给定的表达式树(二叉树)转换为等价的中缀表达式(通过括号反映操作符的计算次序)并输出。

#include "function.h"

//请设计一个算法,将给定的表达式树(二叉树)转换为等价的中缀表达式(通过括号反映操作符的计算次序)并输出。

//算法思想:中缀表达式由二叉树中序遍历得到,其中需要加上括号。
// 除根结点和叶子结点外,遍历到其它结点时,在遍历其左子树之前加上左括号,遍历完右子树加上右括号。


void TreeToExp(BiTree T,int deep){
    if(T==NULL){   //遍历至空结点则返回
        return;
    }else if(T->lchild==NULL&&T->rchild==NULL){ //叶子结点则直接打印结点值
        printf("%c",T->c);
    }else{
        if(deep>1){   //根结点不加括号
            printf("(");
        }
        TreeToExp(T->lchild,deep+1);
        printf("%c",T->c);
        TreeToExp(T->rchild,deep+1);
        if(deep>1){ //根结点不加括号
            printf(")");
        }
    }
}


void TreeToE(BiTree T){
    TreeToExp(T,1);
}


int main() {
   BiTree tree;
   CreateBiTree(tree);
   printf("InOrder:\n");
   InOrder(tree);
   printf("\nExpression is:\n");
   TreeToE(tree);
}

输出结果:
+*-ab0-0000cd
InOrder:
a*b+-c-d
Expression is:
(a*b)+(-(c-d))
进程已结束,退出代码为 0