PAT A1020. Tree Traversals (25)

原文链接: PAT A1020. Tree Traversals (25)

上一篇: PAT A1091. Acute Stroke (30)

下一篇: PAT A1086. Tree Traversals Again (25)

1020. Tree Traversals (25)

https://www.patest.cn/contests/pat-a-practise/1020

时间限制

400 ms

内存限制

65536 kB

代码长度限制

16000 B

判题程序

Standard

作者

CHEN, Yue

Suppose that all the keys in a binary tree are distinct positive integers. Given the postorder and inorder traversal sequences, you are supposed to output the level order traversal sequence of the corresponding binary tree.

Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N (<=30), the total number of nodes in the binary tree. The second line gives the postorder sequence and the third line gives the inorder sequence. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print in one line the level order traversal sequence of the corresponding binary tree. All the numbers in a line must be separated by exactly one space, and there must be no extra space at the end of the line.

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

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>

using namespace std;

const int MAX = 50;

struct Node {
	int data;
	Node *left, *right;
	Node() {}
	Node(int data) :data(data) {
		left = right = NULL;
	}
};

int pre[MAX], in[MAX], post[MAX];	//先序,中序,后序序列
int n;	//节点个数

		//当前二叉树的后序序列区间[postL,postR],中序区间[inL,inR]
Node* create(int postL, int postR, int inL, int inR) {
	if (postL > postR) return NULL;
	Node *root = new Node(post[postR]);
	int k;
	for (k = inL; k <= inR; k++) {
		if (in[k] == post[postR])
			break;		//在中序中找in[k] == pre[l]的节点 
	}
	int numLeft = k - inL;	//左子树节点个数
	root->left = create(postL, postL + numLeft - 1, inL, k - 1);
	root->right = create(postL + numLeft, postR - 1, k + 1, inR);
	return root;
}

int num = 0;	//已输出节点个数
void bfs(Node* root) {
	queue<Node*> q;
	q.push(root);
	while (!q.empty()) {
		Node *now = q.front();
		q.pop();
		printf("%d", now->data);
		num++;
		if (num < n) printf(" ");
		if (now->left) q.push(now->left);
		if (now->right) q.push(now->right);
	}
}
int main(int argc, char *argv[]) {
	scanf("%d", &n);
	for (int i = 0; i < n; i++) {
		scanf("%d", post + i);
	}

	for (int i = 0; i < n; i++)
		scanf("%d", in + i);
	Node *root = create(0, n - 1, 0, n - 1);
	bfs(root);
	return 0;
}

不用建树的做法

已知后序与中序输出前序(先序):
后序:3, 4, 2, 6, 5, 1(左右根)
中序:3, 2, 4, 1, 6, 5(左根右)
分析:因为后序的最后一个总是根结点,令i在中序中找到该根结点,则i把中序分为两部分,左边是左子树,右边是右子树。因为是输出先序(根左右),所以先打印出当前根结点,然后打印左子树,再打印右子树。左子树在后序中的根结点为root – (end – i + 1),即为当前根结点-右子树的个数。左子树在中序中的起始点start为start,末尾end点为i – 1.右子树的根结点为当前根结点的前一个结点root – 1,右子树的起始点start为i+1,末尾end点为end。
输出的前序应该为:1, 2, 3, 4, 5, 6(根左右)

#include <cstdio>
using namespace std;
int post[] = {3, 4, 2, 6, 5, 1};
int in[] = {3, 2, 4, 1, 6, 5};
void pre(int root, int start, int end) {
    if(start > end) return ;
    int i = start;
    while(i < end && in[i] != post[root]) i++;
    printf("%d ", post[root]);
    pre(root - 1 - end + i, start, i - 1);
    pre(root - 1, i + 1, end);
}

int main() {
    pre(5, 0, 5);
    return 0;
}

题目大意:给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。
分析:与后序中序转换为前序的代码相仿(无须构造二叉树再进行广度优先搜索~~),只不过加一个变量index,表示当前的根结点在二叉树中所对应的下标(从0开始),所以进行一次输出先序的递归的时候,就可以把根结点下标所对应的值存储在level数组中(一开始把level都置为-1表示此处没有结点),这样在递归完成后level数组中非-1的数就是按照下标排列的层序遍历的顺序~~~

#include <cstdio>
#include <vector>
using namespace std;
vector<int> post, in, level(100000, -1);
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++;
    level[index] = post[root];
    pre(root - 1 - end + i, start, i - 1, 2 * index + 1);
    pre(root - 1, i + 1, end, 2 * index + 2);
}
int main() {
    int n, cnt = 0;
    scanf("%d", &n);
    post.resize(n);
    in.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);
    for(int i = 0; i < level.size(); i++) {
        if(level[i] != -1 && cnt != n - 1) {
            printf("%d ", level[i]);
            cnt++;
        } else if(level[i] != -1){
            printf("%d", level[i]);
            break;
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值