二叉树遍历--前序+中序生成后序

给定一棵二叉树的前序遍历和中序遍历,求其后序遍历(提示:给定前序遍历与中序遍历能够唯一确定后序遍历)。

输入描述:
两个字符串,其长度n均小于等于26。
第一行为前序遍历,第二行为中序遍历。
二叉树中的结点名称以大写字母表示:A,B,C....最多26个结点。
输出描述:
输入样例可能有多组,对于每组测试样例,
输出一行,为后序遍历的字符串。
如:
输入:
ABC
BAC
FDXEAG
XDEFAG
输出:
BCA
XEDGAF

思路:先序+中序求后序,先序的第一个字符是根root,所以得在中序序列中遍历找出root所在位置,设由中序第一位向前挪i次后找到root,将中序一分为二,root的左子树和右子树,则相应的,前序中也可划分出左子树和右子树,只是现在只知道前序和中序的首地址,所以再加上长度len和挪动的次数就可以在前序,中序中分离出左和右。

#include <iostream>
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
using namespace std;

typedef struct Tnode{
    char ch;
    Tnode *lc;
    Tnode *rc;
}Tnode;


Tnode *Create_Tree(Tnode *T,char *pre,char *in,int len){
    T=(Tnode*)malloc(sizeof(Tnode));
    T->lc=T->rc=NULL;//初始化节点,无值;
    if(len<=0){//若剩余长度<=0,停止;否则继续遍历查找
        T=NULL;
    }
    else{

            int i=0;
            while(*(pre)!=*(in+i)&&i<=len){//这里使用指针类型更方便,找出root在中序序列中的位置
                i++;
            }
            T->ch=*pre;
            T->lc=Create_Tree(T->lc,pre+1,in,i);/*这里preoder+1是指前序序列中的首元素已经确定位置了,所以前序序列需向前移动一位,而中序序列还是in是因为它没法指定自己的区间,但是有了长度i就可以了,区间是从0---i-1;所以此处无论是pre 还是in ,都是指向自己的起始地址,借助i可以知道截止地址在哪; */
            T->rc=Create_Tree(T->rc,pre+1+i,in+i+1,len-1-i);

    }
    return T;


}

void PostPrint(Tnode *T){
    if(T){
        PostPrint(T->lc);
        PostPrint(T->rc);
        cout<<T->ch;
    }
}

int main()
{
    char pre[27],in[27];
    while(cin>>pre){
        cin>>in;
        Tnode *T=NULL;
        int len=strlen(pre);
        T=Create_Tree(T,pre,in,len);
        PostPrint(T);
        cout<<endl;
    }
    return 0;
}

NOTE:
难点:递归解决该问题:首先在前序序列中找根root,即前序序列第一个字母,然后在中序序列中找对应的字母,此时root将中序序列分为左根右三部分,保存root,再在左子树中递归,在右子树中递归,直到树的长度小于等于0;所以需要有一个长度变量,不仅提示是否退出递归,而且也容易区分左右子树的遍历区间;
1.由前序和中序序列重新建树时,忘了要写递归截止条件,即当长度<=0时退出递归;
2. char*和char[]的区别----前者表示元素char *ch; (ch)表示第一个字符
3. 主函数中定义前序序列preorder[],中序序列inorder[]为char型数组,直接分配空间,而不是char
型;

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值