PAT_甲级_1020 Tree Traversals (25分) (C++)【树的遍历】

目录

1,题目描述

 题目大意

2,思路

树的遍历

数据结构 

关键点

3,代码


1,题目描述

Sample Input:

7
2 3 1 5 7 6 4
1 2 3 4 5 6 7

 

Sample Output:

4 1 6 3 5 7 2

 题目大意

根据给出的二叉树的postorder(后序遍历) and inorder(中序遍历),输出level(层次遍历)

 

 

 

 

2,思路

参考柳神的思路。

学过数据结构的同学可能比较清楚,通过树的中序和后序遍历,可以构建一颗完整的二叉树,根据得出的二叉树并利用队列,可以得到层次遍历。

在这里,可以利用中序和后续遍历推出先序遍历,只需要在先序遍历过程中记录节点的下标,按下标排序后,输出的值即为层次遍历的输出结果。

 

树的遍历

由中序和后序遍历如何推出二叉树,可以参考这篇文章@那记忆微凉 【已知中序遍历和后序遍历,画出此二叉树】

  • 先序遍历:根左右
  • 中序遍历:左根右
  • 后序遍历:左右根

数据结构 

  • struct node{int index, value;}:index按层次遍历时输出的先后顺序,value输出的值;
  • vector<int> in, post:存放树的两种遍历顺序;
  • vector<node> ans:存放最终答案

关键点

以题目中所给例子为参考: 

postOrder:2 3 1 5 7 6 4

inOrder:1 2 3 4 5 6 7

  • 后序遍历的最后一个节点(4)为二叉树的根节点。这个根节点将整棵树(中序遍历中)分成了左右两棵子树,左子树节点为1 2 3、右子树节点为5 6 7;
  • 在后序遍历(2 3 1 5 7 6 4)中可以看出,左子树的根节点为1,右子树的根节点为6;(将一棵大树,划分为两棵小树,这就是递归的原理)
  • 具体实现时,以后序遍历为准,在中序遍历找到根节点位置得出左右子树的节点数目,确定后序遍历新的始末位置,进行递归;
  • 显然在遍历过程中,先确定根节点,然后确定左右子树的根节点……这便是层次遍历的输出顺序,因此,在遍历时,只需加上index值,使其在向下遍历时不断递增(左子树:2*index+1, 右子树:2*index+2),然后按照index排序,输出value值即可;
  • pre(root-(end-i)-1, start, i - 1, 2 * index + 1)(递归求左子树)这里说明一下,左子树的根节点如何确定:root(原根节点在后序遍历中的位置),i(根节点在中序遍历中的位置),end-i(右子树节点数目),-1(即左子树根节点在后序遍历中的位置);

3,代码

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

struct node{
    int index, value;
};
bool cmp(node a, node b){
    return a.index < b.index;
}
vector<node> ans;
vector<int> in, post;

//root start end均指后序遍历时的下标 
void pre(int root, int start, int end, int index){      //递归实现
    if(start > end) return;//
    int i = start;
    while(i <= end && in[i] != post[root]) i++;         //找到根节点(后序遍历的最后一个节点)在中序遍历序列中的位置
    ans.push_back({index, post[root]});                 //根节点入栈
    pre(root-(end-i)-1, start, i - 1, 2 * index + 1);   //递归处理左右两棵子树 并更新index(index可能不连续)
    pre(root - 1, i + 1, end, 2 * index + 2);           

}

int main(){
//#ifdef ONLINE_JUDGE
//#else
//    freopen("1.txt", "r", stdin);
//#endif

    int n;
    scanf("%d", &n);
    in.resize(n);
    post.resize(n);
    for(int i = 0; i < n; i++) scanf("%d", &post[i]);
    for(int i = 0; i < n; i++) scanf("%d", &in[i]);

    pre(n-1, 0, n-1, 0);                                
    sort(ans.begin(), ans.end(), cmp);
    printf("%d", ans[0].value);
    for(int i = 1; i < ans.size(); i++){
        printf(" %d", ans[i].value);
    }

    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值