数据结构实验四(C语言):二叉树的建立与应用

【实验目的】

  1. 熟练掌握树的基本概念、二叉树的基本操作及在链式存储结构上的实现。
  2. 重点掌握二叉树的生成、遍历及求深度等算法。
  3. 掌握二叉树的线索化及线索二叉树的遍历算法;掌握赫夫曼树的含义及其应用。
  4. 掌握运用递归方式描述算法及编写递归C程序的方法,提高算法分析和程序设计能力。
    【问题描述】
    二叉树采用二叉链表作存储结构,试编程实现二叉树的如下基本操作:
  5. 按先序序列构造一棵二叉链表表示的二叉树T;
  6. 对这棵二叉树进行遍历:先序、中序、后序以及层次遍历序列,分别输出结点的遍历序列;
  7. 求二叉树的深度。
    4.求叶子结点的个数。
  8. 将二叉树每个结点的左右子树交换位置。
    要求设计一漂亮、实用的功能菜单,每个功能用一函数表示。
    【测试数据】
  9. 输入:#↙,建立一棵空树,
    先序、中序、后序遍历和层次遍历没有输出,树的深度输出为0;
    叶子结点个数为;0。
  10. 输入:A↙
    先序、中序、后序遍历和层次遍历输出均为A;
    深度输出为:1 ;
    叶子结点个数为:1
  11. 输入:ABC##DE#G##F###↙,
    先序输出为: A B C D E G F
    中序序列为: C B E G D F A
    后序序列为: C G E F D B A
    层次遍历输出为:A B C D E F G
    深度输出为: 5
    叶子结点个数为:3
  12. 输入:     ABD#GJ##K##E##C#FH##IL###↙,
    先序遍历输出为:A B D G J K E C F H I L
    层次遍历输出为:A B C D E F G H I J K L
    中序序列为: D J G K B E A C H F L I
    后序序列为: J K G D E B H L I F C A
    深度输出为: 5
    叶子结点个数为:5
    【说明】
  13. 按先序次序输入二叉树中结点的值,用’#'表示空树,对每一个结点应当确定其左右子树的值(为空时必须用特定的空字符占位),故执行此程序时,最好先在纸上画出你想建立的二叉树,每个结点的左右子树必须确定,若为空,则用特定字符标出,然后再按先序输入这棵二叉树的字符序列;
  14. 为了简化程序的书写量,以及程序的清晰性,对结点的访问以一条输出语句表示,若有更复杂的或多种访问,可以将结点的访问编写成函数,然后通过函数指针进行函数的调用。读者若有兴趣,可自行编写。
  15. C语言函数参数传递,都是“传值”的方式,故在设计函数时,必须注意参数的传递,若想通过函数修改实际参数的值,必须对指针变量作参数。具体设计时,读者一定要把指针变量、指针变量指向的值等概念弄清楚;
  16. 对于其他算法,请读者思考,自行编程完成,以加深学习体会。
    【提高题】
    有能力的同学,可以继续完成下面2道题。
  17. 按中序顺序建立一棵二叉树;
  18. 用非递归方式遍历二叉树(先序、中序或后序),输出遍历序列。
#include<stdio.h>
#include<stdlib.h>
#define MaxSize 100
/*二叉树的二叉链表存储结构*/
typedef char dataType;
typedef struct node
{
    dataType data;
    struct node *lchild, *rchild; /**左右孩子指针**/
} *BinTree,BinNode; /**结点类型**/
typedef BinTree QelemType;
typedef struct
{
    QelemType num[MaxSize];
    int front;
    int rear;
} Queue;
Queue Q;
void initilize()   ///初始化队列
{
    Q.front = 0;
    Q.rear = 0;
}
int Push(BinNode *T)   ///入队
{
    if((Q.rear+1)==Q.front)
        return 0;
    else
        Q.num[++Q.rear] = T;
    return 1;
}

BinNode *Pop()   ///出队
{
    if(Q.front==Q.rear)
        return 0;
    return Q.num[++Q.front];
}

int Empty()   ///判断对列是否为空
{
    if(Q.front==Q.rear)
        return 1;
    else
        return 0;
}
///建立二叉树
int CreateBiTree(BinTree &T)///输入字符序列,先序遍历建立二叉链表
{
    char ch;
    ch = getchar(); ///输入一个字符
    if(ch == '#')
    {
        T = NULL;
    }
    else ///如果结点不为空
    {
        T = (BinNode*)malloc(sizeof(BinNode)); ///申请一个结点空间
        if(!T)
        {
            return 0;
        }
        T->data = ch;
        CreateBiTree(T->lchild);///创建左子树
        CreateBiTree(T->rchild);///创建右子树
    }
    return 1;
}
///中序遍历
void inOder(BinTree T)
{
    if(!T)
        return ;
    if(T)
    {
        inOder(T->lchild);
        printf("%c ", T->data);
        inOder(T->rchild);
    }
}
///先序遍历
void PreOder(BinTree T)
{
    if(!T)
        return ;
    if(T)
    {
        printf("%c ", T->data);
        PreOder(T->lchild);
        PreOder(T->rchild);
    }
}
///后序遍历
void PostOder(BinTree T)
{
    if(!T)
        return ;
    if(T)
    {
        PostOder(T->lchild);
        PostOder(T->rchild);
        printf("%c ", T->data);
    }
}
///二叉树的层次遍历
void LevelOrder(BinTree T)
{
    BinNode *temp;
    if(!T)
        return;
    Push(T);
    while (!Empty())
    {
        temp = Pop();
        printf("%c ", temp->data);  ///输出队首结点
        if(temp->lchild)     ///把Pop掉的结点的左子结点加入队列
            Push(temp->lchild);
        if(temp->rchild)    ///把Pop掉的结点的右子结点加入队列
            Push(temp->rchild);
    }
}
///二叉树的深度
int Depth(BinTree T)
{
    int hl, hr;
    if(!T)
        return 0;
    else
    {
        hl = Depth(T->lchild);
        hr = Depth(T->rchild);
        if(hl >= hr)
            return hl + 1;
        else
            return hr + 1;
    }
}
///求叶子节点的个数
void CountLeaf(BinTree T,int &cnt)
{
    if(T)
    {
        if((!T->lchild) && (!T->rchild))
            cnt++;
        CountLeaf(T->lchild,cnt);
        CountLeaf(T->rchild,cnt);
    }
}
///交换左右子树
int exchange(BinTree &T)
{
    BinNode *temp;
    if(!T)
        return 0;
    if(T->lchild == NULL && T->rchild == NULL)
        return 0;
    else
    {
        temp = T->lchild;
        T->lchild = T->rchild;
        T->rchild = temp;
    }
    if(T->lchild)
        exchange(T->lchild);
    if(T->rchild)
        exchange(T->rchild);
    return 1;
}
void menu()
{
    printf("--------------------二叉树的建立与应用-------------------------\n");
    printf("\t1.二叉树的中序遍历\n");
    printf("\t2.二叉树的前序遍历\n");
    printf("\t3.二叉树的后序遍历\n");
    printf("\t4.二叉树的层次遍历\n");
    printf("\t5.二叉树的深度\n");
    printf("\t6.二叉树叶子结点的个数\n");
    printf("\t7.二叉树每个结点的左右子树交换位置\n");
    printf("\t8.退出系统\n");
    printf("----------------------------------------------------------------\n");
}
int main()
{
    BinTree T;
    int m,cnt=0;
    menu();
    printf("按先序序列创建一个二叉树:\n");
    if(CreateBiTree(T)==1)
        printf("创建成功!\n");
    while(1)
    {
        scanf("%d", &m);
        if(m == 1)
        {
            printf("中序遍历为:\n");
            inOder(T);
            printf("\n");
        }
        else if(m == 2)
        {
            printf("先序遍历为:\n");
            PreOder(T);
            printf("\n");
        }
        else if(m == 3)
        {
            printf("后序遍历为:\n");
            PostOder(T);
            printf("\n");
        }
        else if(m == 4)
        {
            printf("层次遍历为:\n");
            initilize();
            LevelOrder(T);
            printf("\n");
        }
        else if(m == 5)
        {
            printf("二叉树深度为:\n");
            printf("%d\n", Depth(T));
        }
        else if(m == 6)
        {
            printf("二叉树叶子结点数为:\n");
            CountLeaf(T,cnt);
            printf("%d\n",cnt);
        }
        else if(m == 7)
        {
            printf("左右子树进行交换:\n");
            if(exchange(T)==1)
                printf("交换完成!\n");
            printf("交换后中序遍历为:\n");
            inOder(T);
            printf("\n");
            printf("交换后先序遍历为:\n");
            PreOder(T);
            printf("\n");
            printf("交换后后序遍历为:\n");
            PostOder(T);
            printf("\n");
            printf("交换后层次遍历为:\n");
            initilize();
            LevelOrder(T);
            printf("\n");
        }
        else
            break;
    }
    return 0;
}
  • 5
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值