【二叉树】已知一个二叉树的中序遍历序列和后序遍历序列,求这棵树的前序遍历序列

本文采用C语言,主要熟练掌握另一种通过中序遍历和后序遍历构建二叉树的基本方法(通过前序遍历和中序遍历构建二叉树原理相同)


自然界中的二叉树

【问题描述】

已知一个二叉树的中序遍历序列和后序遍历序列,求这棵树的前序遍历序列。

【输入形式】

一个树的中序遍历序列 该树后序遍历序列,中间用空格分开。输入序列中仅含有小写字母,且没有重复的字母

【输出形式】

一个树的前序遍历序列

【样例输入】

dbeafcg debfgca

【样例输出】

abdecfg


通过中序遍历和后序遍历以及通过前序遍历和中序遍历可唯一确定一颗二叉树,注意一定要有中序遍历,由于前序遍历第一个结点为树的根结点,后序遍历最后一个结点为树的根结点,所以通过中序遍历可由树的根结点将左子树和右子树分开,以便于下面的计算

结点的数目无论使用前,中,还是后序遍历都是相同的
【主要通过每次确定各个子树中根结点的位置以及左,右子树中结点的数目通过递归来求解(也可看作分治求解)】


一、根据中序遍历和后序遍历构建二叉树(忽然觉得带返回值的构建函数更好理解)

(1)第一种方法(带返回值的函数)


//根据中序遍历和后序遍历构建二叉树
BitNode* CreateBiTree(char *instr, char *afterstr, int length)
{
    if (length == 0)//都构建完毕
    {
        return NULL;
    }
    char c = afterstr[length - 1];//树的根为后序遍历最后一个字符
    int i = 0;
    while ((instr[i] != c) && i < length)//找到中序遍历中该根的位置
    {
        i = i + 1;
    }
    int leftlength = i;//确定左子树中结点的数目
    int rightlength = length - i - 1;//确定右子树中结点的数目
    BitNode *T;
    T = (BitNode*)malloc(sizeof(BitNode));
    T->data = c;//建立新结点,每次都使其等于每棵小子树的根结点
    T->lchild = NULL;
    T->rchild = NULL;
    T->lchild = CreateBiTree(&instr[0], &afterstr[0], leftlength);//创建左子树
    T->rchild = CreateBiTree(&instr[i + 1], &afterstr[i], rightlength);//创建右子树
    return T;
}

(2)返回值为void的函数

注意递归调用跳出函数的条件,即注意if,else的使用,以及函数递归调用实参中T->lchild以及 T->rchild的使用


//根据中序遍历和后序遍历构建二叉树
void CreateBiTree(BitNode **T,char *instr, char *afterstr, int length)
{
    if (length == 0)//都构建完毕
    {
        *T = NULL;
    }
    else//注意else的使用,便于跳出无返回值的函数
    {
        char c = afterstr[length - 1];//树的根为后序遍历最后一个字符
        int i = 0;
        while ((instr[i] != c) && i < length)//找到中序遍历中该根的位置
        {
            i = i + 1;
        }
        int leftlength = i;//确定左子树中结点的数目
        int rightlength = length - i - 1;//确定右子树中结点的数目
        *T = (BitNode*)malloc(sizeof(BitNode));
        (*T)->data = c;//建立新结点,每次都使其等于每棵小子树的根结点
        (*T)->lchild = NULL;
        (*T)->rchild = NULL;
        CreateBiTree(&((*T)->lchild), &instr[0], &afterstr[0], leftlength);//创建左子树
        CreateBiTree(&((*T)->rchild), &instr[i + 1], &afterstr[i], rightlength);//创建右子树
    }
}

二、前序遍历输出


//前序遍历输出
void PreOrderTraverse(BitNode *T)
{
    if (T)
    {
        printf("%c", T->data);
        PreOrderTraverse(T->lchild);
        PreOrderTraverse(T->rchild);
    }
}


完整代码如下(附详细注释)


#include
#include
#include
#define MAXSIZE 100
typedef struct BitNode
{
    int data;
    struct BitNode *lchild;
    struct BitNode *rchild;
}BitNode;
//根据中序遍历和后序遍历构建二叉树
BitNode* CreateBiTree(char *instr, char *afterstr, int length)
{
    if (length == 0)//都构建完毕
    {
        return NULL;
    }
    char c = afterstr[length - 1];//树的根为后序遍历最后一个字符
    int i = 0;
    while ((instr[i] != c) && i < length)//找到中序遍历中该根的位置
    {
        i = i + 1;
    }
    int leftlength = i;//确定左子树中结点的数目
    int rightlength = length - i - 1;//确定右子树中结点的数目
    BitNode *T;
    T = (BitNode*)malloc(sizeof(BitNode));
    T->data = c;//建立新结点,每次都使其等于每棵小子树的根结点
    T->lchild = NULL;
    T->rchild = NULL;
    T->lchild = CreateBiTree(&instr[0], &afterstr[0], leftlength);//创建左子树
    T->rchild = CreateBiTree(&instr[i + 1], &afterstr[i], rightlength);//创建右子树
    return T;
}
//前序遍历输出
void PreOrderTraverse(BitNode *T)
{
    if (T)
    {
        printf("%c", T->data);
        PreOrderTraverse(T->lchild);
        PreOrderTraverse(T->rchild);
    }
}
int main()
{
    char instr[MAXSIZE];
    char afterstr[MAXSIZE];
    scanf("%s", instr);
    scanf("%s", afterstr);
    int length = strlen(instr);//结点的数目无论前,中,后序遍历都是相同的
    BitNode *T;
    T = (BitNode*)malloc(sizeof(BitNode));
    T = CreateBiTree(instr, afterstr, length);
    PreOrderTraverse(T);
    return 0;
}


运行结果

越努力,越幸运

end~~~

你可能感兴趣的:(【二叉树】已知一个二叉树的中序遍历序列和后序遍历序列,求这棵树的前序遍历序列)