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

  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);
	}
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值