利用前序和后序遍历序列构建真二叉树的构建

利用前序和后序序列构建真二叉树

一般来讲,给定二叉树的先序遍历序列和后序遍历序列,不能唯一确定这棵二叉树。但 是,对于真
二叉树来讲,给定它的先序遍历序列 pre 和后序遍历序列 post,可以唯一确定这 棵真二叉树。所谓真
二叉树是指每个内部节点都有两个孩子的二叉树。
根据真二叉树的先序遍历序列 pre 和后序遍历序列 post,编写一个实现真二叉树的构造 及中序遍
历的程序,要求如下:
(1)具有操作界面;
(2)可以测试多组数据,每组数据的真二叉树先序遍历序列 pre、后序遍历序列 post 通过键盘输

( 3 ) 将 先 序 遍 历 序 列 pre 、 后 序 遍 历 序 列 post 、 中 序 遍 历 序 列 in 保 存 到 文 本 文 件
proper-bitree.txt 中, 格式如下:
真二叉树的先序遍历序列 pre
真二叉树的后序遍历序列 post
真二叉树的中序遍历序列 in

分析:二叉树前序遍历的第一个元素和后序遍历的最后一个元素为树根,后序遍历序列的倒数第二个元素为右子树的根,前序遍历中右子树的根的前面的元素均为左子树元素,从而分隔左右子树的元素,据此可以采用递归依次构建每一棵子树。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
typedef struct BitNode
{
    char data;
    struct BitNode *lchild;
    struct BitNode *rchild;
} BitNode;
 
BitNode *Creat_ProperBiTree(char *pre, char *post, int length, int *tag); //前序后序转中序
void InOrderTraverse(BitNode*T);
 
int main(void)
{
    int c;
    while(1)
    {
        printf("请开始选择:0、构造真二叉树,1、退出\n");
        scanf("%d", &c);
        fflush(stdin);
        switch(c)
        {
        case 0:
        {
            FILE *fp ;
            int tag = 0;//标记错误,0为无错误
            if((fp = fopen("proper-bitree.txt", "a")) == NULL)
            {
                printf("打开文件失败\n");
                exit(EXIT_FAILURE);
            }
            system("cls");
            char pre[1024];
            char post[1024];
            //文件写入前序序列
            printf("请输入前序输出序列(不要有空格)\n");
            gets(pre);
            fputs(pre, fp);
            fprintf(fp, "\n");
            //文件写入后序序列
            printf("请输入后序输出序列(不要有空格)\n");
            gets(post);
            fputs(post, fp);
            fprintf(fp, "\n");
            fclose(fp);
            int prelength = strlen(pre);
            int postlength = strlen(post);
            if(prelength != postlength || prelength % 2 == 0 || postlength % 2 == 0)
            {
                tag = 1;//长度不符合要求,设置错误
            }
            //开始构造真二叉树
            BitNode* T;
            T = Creat_ProperBiTree(pre, post, prelength, &tag);//tag指示是否出错
 
            if(tag == 0)
            {
                InOrderTraverse(T);
                if((fp = fopen("proper-bitree.txt", "a")) == NULL)
                {
                    printf("打开文件失败\n");
                    exit(EXIT_FAILURE);
                }
                fprintf(fp, "\n");//行末增加换行
                fclose(fp);
                printf("结果已写入文件\n");
            }
            else
            {
                if((fp = fopen("proper-bitree.txt", "a")) == NULL)
                {
                    printf("打开文件失败\n");
                    exit(EXIT_FAILURE);
                }
                fprintf(fp, "对不起,输入的序列无法构成真二叉树\n");
                fclose(fp);
                printf("结果已写入文件\n");
            }
            system("pause");
        }
        break;
        case 1:
        {
            return 0;
            break;
        }
        default:
            printf("输入错误,请重新输入\n");
            break;
        }
    }
    return 0;
}
 
 
void InOrderTraverse(BitNode*T)
{
    if(T)
    {
        InOrderTraverse(T->lchild);
        //在文件中写入中序遍历序列
        FILE *fp1;
        if((fp1 = fopen("proper-bitree.txt", "a")) == NULL)
        {
            printf("打开文件失败\n");
            exit(EXIT_FAILURE);
        }
        fputc(T->data, fp1);
        fclose(fp1);
        InOrderTraverse(T->rchild);
    }
}
 
BitNode *Creat_ProperBiTree(char *pre, char *post, int length, int *tag) //前序后序转中序
{
    if(length == 1)//有一个节点,必为根
    {
        BitNode* T = (BitNode*)malloc(sizeof(BitNode));
        if(pre[0] == post[0])//唯一的节点相同
        {
            T->data = pre[0];
            T->lchild = NULL;
            T->rchild = NULL;
            return T;
        }
        else//唯一的节点不相同,必错误
        {
            *tag = 1;
            return NULL;
        }
    }
    if(length % 2 == 0)//序列长度为偶数,无法构成真二叉树
    {
        *tag = 1;
        return NULL;
    }
 
    int i = 0;
    if(pre[0] != post[length - 1])//在前序和后序遍历序列中找到的根不一样
    {
        *tag = 1;//设置错误
        return NULL;
    }
 
    char Root = pre[0];//根
    char rightRoot = post[length - 2]; //右子树根
    while(pre[i] != rightRoot && i < length)
    {
        i++;//在前序遍历中找到右子树的根,从而分隔左右子树
    }
    if( i == length )
    {
        *tag = 1;//在前序序列没找到右子树的根,错误
        return NULL;
    }
 
    int leftlength = i - 1;//左子树节点个数
    int rightlength = length - i;//右子树节点个数
 
    BitNode * T = (BitNode*)malloc(sizeof(BitNode));
    T->data = Root;
 
    T->lchild = Creat_ProperBiTree(&pre[1], &post[0], leftlength,tag);
    T->rchild = Creat_ProperBiTree(&pre[i], &post[i - 1], rightlength,tag);
    return T;
}

注:文件指针做成全局变量更好,会节省不少行代码,也可以提高代码运行效率。(懒得不想改了)

附上流程图:
在这里插入图片描述

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值