1119. Pre- and Post-order Traversals (30)解题报告

本文介绍了一种根据前序遍历和后序遍历序列还原二叉树的方法,并提供了两个不同版本的C++实现代码。通过这些代码,可以验证输入的遍历序列是否能唯一确定一棵二叉树,并输出该二叉树的中序遍历结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 前序遍历是MLR,后序遍历是LRM。
  2. 前序的第一个元素和后续遍历的后一个元素就是根结点。
  3. 如果在子序列中前序的第一个元素等于后序的最后一个元素,那么存在多解。本程序中遇到有多种可能时,都把子序列挂到父节点的左边。
  4. 如果子序列中前序的第一个元素不等于后序的最后一个元素,那么前者是父节点的左孩子,后者是父节点的右孩子。
  5. 父节点的左孩子在后序遍历中位于L的最后一位。
  6. 父节点的右孩子在前序遍历中位于R第一位。由此可得到L的元素数量和R的元素数量。
第一个版本
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <set>

using namespace std;

struct node {
	int key;
	node *left, *right;
};

void recovery(int start1, int start2, int cnt, node *&root);
void inorder(node *root);
int	pre[40], post[40];
bool flag = true;
queue<int> in;
int main(void)
{
	int	i, n;
	node *root;
	scanf("%d", &n);
	for (i = 0; i < n; i++) {
		scanf("%d", pre + i);
	}
	for (i = 0; i < n; i++) {
		scanf("%d", post + i);
	}
	root = new node;
	root->key = pre[0];
	root->left = root->right = nullptr;
	recovery(1, 0, n - 1, root);
	if (flag) {
		puts("Yes");
	}
	else {
		puts("No");
	}
	inorder(root);
	printf("%d", in.front());
	in.pop();
	while (!in.empty()) {
		printf(" %d", in.front());
		in.pop();
	}
	putchar('\n');
	return 0;
}

void recovery(int start1, int start2, int cnt, node *&r) {
	node *root = nullptr;
	if (cnt < 1) {
		return;
	}
	else if (pre[start1] == post[start2 + cnt - 1]) {
		flag = false;
		root = new node;
		root->left = root->right = nullptr;
		root->key = pre[start1];
		r->left = root;
		recovery(start1 + 1, start2, cnt - 1, root);
	}
	else if (pre[start1] != post[start2 + cnt - 1]) {
		int i, j, preleft, num;
		preleft = pre[start1];
		for (i = start2; i < start2 + cnt; i++) {
			if (post[i] == preleft) {
				break;
			}
		}
		num = i - start2 + 1;
		node *left, *right;
		left = new node;
		right = new node;
		left->key = pre[start1];
		right->key = post[start2 + cnt - 1];
		left->left = left->right = right->left = right->right = nullptr;
		r->left = left;
		r->right = right;
		recovery(start1 + 1, start2, num - 1, left);
		recovery(start1 + num + 1, start2 + num, cnt - 1 - num, right);
	}
}

void inorder(node *root) {
	if (root) {
		inorder(root->left);
		in.push(root->key);
		inorder(root->right);
	}
}


第二个版本

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <set>

using namespace std;

struct node {
	int key;
	node *left, *right;
};

void recovery(int start1, int start2, int cnt, node *&root);
void inorder(node *root);
int	pre[40], post[40];
bool flag1 = true, flag2 = true;
queue<int> in;
int main(void)
{
	int	i, n;
	node *root;
	scanf("%d", &n);
	for (i = 0; i < n; i++) {
		scanf("%d", pre + i);
	}
	for (i = 0; i < n; i++) {
		scanf("%d", post + i);
	}
	root = nullptr;
	recovery(0, 0, n, root);
	if (flag2) {
		puts("Yes");
	}
	else {
		puts("No");
	}
	inorder(root);
	printf("%d", in.front());
	in.pop();
	while (!in.empty()) {
		printf(" %d", in.front());
		in.pop();
	}
	putchar('\n');
	return 0;
}

void recovery(int start1, int start2, int cnt, node *&r) {
	node *root = nullptr;
	if (cnt < 1) {
		return;
	}
	else if (pre[start1] == post[start2 + cnt - 1]) {
		flag2 = flag1;
		flag1 = false;
		if (r == nullptr) {
			r = new node;
			r->key = pre[start1];
			r->left = r->right = nullptr;
			recovery(start1 + 1, start2, cnt - 1, r);
		}
		else {
			root = new node;
			root->left = root->right = nullptr;
			root->key = pre[start1];
			r->left = root;
			recovery(start1 + 1, start2, cnt - 1, root);
		}
	}
	else if (pre[start1] != post[start2 + cnt - 1]) {
		int i, j, preleft, num;
		preleft = pre[start1];
		for (i = start2; i < start2 + cnt; i++) {
			if (post[i] == preleft) {
				break;
			}
		}
		num = i - start2 + 1;
		node *left, *right;
		left = new node;
		right = new node;
		left->key = pre[start1];
		right->key = post[start2 + cnt - 1];
		left->left = left->right = right->left = right->right = nullptr;
		r->left = left;
		r->right = right;
		recovery(start1 + 1, start2, num - 1, left);
		recovery(start1 + num + 1, start2 + num, cnt - 1 - num, right);
	}
}

void inorder(node *root) {
	if (root) {
		inorder(root->left);
		in.push(root->key);
		inorder(root->right);
	}
}


American Heritage 题目描述 Farmer John takes the heritage of his cows very seriously. He is not, however, a truly fine bookkeeper. He keeps his cow genealogies as binary trees and, instead of writing them in graphic form, he records them in the more linear tree in-order" and tree pre-order" notations. Your job is to create the `tree post-order" notation of a cow"s heritage after being given the in-order and pre-order notations. Each cow name is encoded as a unique letter. (You may already know that you can frequently reconstruct a tree from any two of the ordered traversals.) Obviously, the trees will have no more than 26 nodes. Here is a graphical representation of the tree used in the sample input and output: C / \ / \ B G / \ / A D H / \ E F The in-order traversal of this tree prints the left sub-tree, the root, and the right sub-tree. The pre-order traversal of this tree prints the root, the left sub-tree, and the right sub-tree. The post-order traversal of this tree print the left sub-tree, the right sub-tree, and the root. ---------------------------------------------------------------------------------------------------------------------------- 题目大意: 给出一棵二叉树的中序遍历 (inorder) 和前序遍历 (preorder),求它的后序遍历 (postorder)。 输入描述 Line 1: The in-order representation of a tree. Line 2: The pre-o rder representation of that same tree. Only uppercase letter A-Z will appear in the input. You will get at least 1 and at most 26 nodes in the tree. 输出描述 A single line with the post-order representation of the tree. 样例输入 Copy to Clipboard ABEDFCHG CBADEFGH 样例输出 Copy to Clipboard AEFDBHGC c语言,代码不要有注释
最新发布
06-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值