PAT A1119 Pre- and Post-order Traversals (30 分) 树遍历

60 篇文章 0 订阅

    题目大意:给出二叉树的先序和后序序列,判断能否构成一棵唯一的二叉树。并输出中序遍历的结果。

    与常规问题不同,需要考虑怎么从先序和后序序列中得到左右子树。例如,先序序列的范围是[ prel, prer ],后序序列的范围是[ postl, postr ],那么,显然 prel 和 postr 对应的都是当前树的根节点 root,[prel +1, prer] 包含左右子树,prel + 1是左或右子树的根节点; [postl, postr-1]包含左右子树,postr - 1是左或右子树的根节点。如果 prel +1 和 postr - 1 对应的不是一个节点,说明左子树和右子树都存在;否则说明剩下的节点全在一棵子树上,就无法确定是左子树还是右子树,从而不唯一。如果 prel + 1 和 posrt -1 对应的不是同一个节点,那么在后序序列中找到 与prel + 1对应的节点,从它往左就是左子树(含它本身),从它往右就是右子树(不含它本身),从而可以进行递归。

    这里要注意如果左右子树只存在一棵的话,左子树的节点数量如果用先遍历再减法的方式可能会算错,需要在遍历查找时累加左子树的节点数量,避免错误。另外一个坑点是必须在结尾必须输出换行符,否则会格式错误。

AC代码:

#include <vector>
#include <cstdio>

using namespace std;

struct Node
{
    int data;
    Node* left;
    Node* right;
    Node(int data):data(data), left(NULL), right(NULL){};
};
vector<int> pre;
vector<int> post;
bool determined = true;
Node* root = NULL;
void createFromPrePost(Node* &node, int prel, int prer, int postl, int postr)
{
    if(prel > prer) return;
    if(node == NULL) node = new Node(pre[prel]);
    int index = postl, leftNum = 0;
    for (index = postl; index < postr; ++index)
    {
        leftNum++;
        if(post[index] == pre[prel + 1]) break;
    }
    if(index == postr - 1) determined = false;
    createFromPrePost(node->left, prel+1, prel+leftNum, postl, index);
    createFromPrePost(node->right, prel+leftNum+1, prer, index+1, postr-1);
}

void inOrder(Node* node, int N)
{
    static int printCnt = 0;
    if(node->left) inOrder(node->left, N);
    printf("%d", node->data);
    if(++printCnt < N) printf(" ");
    else printf("\n");
    if(node->right) inOrder(node->right, N);
}

int main()
{
    int N;
    scanf("%d", &N);
    pre.resize(N);
    post.resize(N);
    for (int i = 0; i < N; ++i)
        scanf("%d", &pre[i]);
    for (int i = 0; i < N; ++i)
        scanf("%d", &post[i]);
    createFromPrePost(root, 0, N-1, 0, N-1);
    if(determined) printf("Yes\n");
    else printf("No\n");
    inOrder(root, N);
    return 0;
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值