二叉树遍历 二叉树推导

18 篇文章 0 订阅
11 篇文章 0 订阅

Problem C: 二叉树遍历

题目

Description

二叉树的前序、中序、后序遍历的定义:
前序遍历:对任一子树,先访问跟,然后遍历其左子树,最后遍历其右子树;
中序遍历:对任一子树,先遍历其左子树,然后访问根,最后遍历其右子树;
后序遍历:对任一子树,先遍历其左子树,然后遍历其右子树,最后访问根。
给定一棵二叉树的前序遍历和中序遍历,求其后序遍历(提示:给定前序遍历与中序遍历能够唯一确定后序遍历)。

Input

两个字符串,其长度n均小于等于26。
第一行为前序遍历,第二行为中序遍历。
二叉树中的结点名称以大写字母表示:A,B,C…最多26个结点。

Output

输入样例可能有多组,对于每组测试样例,
输出一行,为后序遍历的字符串。

Sample Input Copy

ABC
CBA
ABCDEFG
DCBAEFG
Sample Output Copy

CBA
DCBGFEA

思路

  • 先由先序遍历和中序遍历推导二叉树,存入结点
    • 该题重点在如何判断根结点和左右子树
    • 每个子树的根结点都在先序遍历的最前端,由此可以找到根结点保存
    • 每个子树的左子树都在中序遍历中根结点左侧,所以可以通过查找到中序中根结点所在位置找到左子树(注意其结点数量与先序遍历相同)
    • 每个子树的左子树都在中序遍历中根结点右侧
    • 因此可以得到该结点左子树和右子树的先序和中序序列,得以进行递归
  • 再通过后序遍历(左右中顺序,使用递归(dfs))输出
  • 如下图(摘选自算法笔记)
    在这里插入图片描述

代码

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

struct Node{
    char num;
    Node* left=NULL;
    Node* right=NULL;
};

string pre;
string in;

Node* resetTree(int preL,int preR,int inL,int inR){//注意不能把Node作为参数,否则会为null
    if(preL>preR||inL>inR)//注意判断是否这一侧子树已经不存在结点
        return NULL;
    Node* root=new Node;
    root->num=pre[preL];
    if(preL==preR)
        return root;
    int i=inL;
    for(i=inL;i<=inR;i++){
        if(pre[preL]==in[i])
            break;
    }
    
    root->left=resetTree(preL+1,preL+i-inL,inL,i-1);//左子树
    root->right=resetTree(preL+i-inL+1,preR,i+1,inR);//右子树
    return root;
}

void postorder(Node* root){
    if(root==NULL)
        return;
    postorder(root->left);
    postorder(root->right);
    printf("%c",root->num);
    return;
}

int main(){
    while(getline(cin,pre)){
        getline(cin,in);
        Node* root=resetTree(0,pre.length()-1,0,in.length()-1);
        postorder(root);
        printf("\n");
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值