03-树3 Tree Traversals Again (25 point(s))

An inorder binary tree traversal can be implemented in a non-recursive way with a stack. For example, suppose that when a 6-node binary tree (with the keys numbered from 1 to 6) is traversed, the stack operations are: push(1); push(2); push(3); pop(); pop(); push(4); pop(); pop(); push(5); push(6); pop(); pop(). Then a unique binary tree (shown in Figure 1) can be generated from this sequence of operations. Your task is to give the postorder traversal sequence of this tree.

Figure1

Input Specification:
Each input file contains one test case. For each case, the first line contains a positive integer N (≤30) which is the total number of nodes in a tree (and hence the nodes are numbered from 1 to N). Then 2N lines follow, each describes a stack operation in the format: “Push X” where X is the index of the node being pushed onto the stack; or “Pop” meaning to pop one node from the stack.

Output Specification:
For each test case, print the postorder traversal sequence of the corresponding tree in one line. A solution is guaranteed to exist. All the numbers must be separated by exactly one space, and there must be no extra space at the end of the line.

Sample Input:

6
Push 1
Push 2
Push 3
Pop
Pop
Push 4
Pop
Pop
Push 5
Push 6
Pop
Pop

Sample Output:

3 4 2 6 5 1

思路如下:
(1)从二叉树的非递归遍历对题目进行分析,可以发现入栈序列可视为先序遍历序列,而出栈序列可视为中序遍历序列,而由先序遍历和中序遍历两个序列就不难得到后序遍历序列;
(2)运用递归将先序遍历序列和中序遍历序列转换为后序遍历序列。由先序遍历序列可找到根节点,再由中序遍历序列即可找到其左右子树在先序、中序遍历序列数组中的起始下标和长度。按照这一思路进行递归;
(3)后序遍历中最后访问根节点,所以将根节点的数值存放在存储后序遍历序列的数组的末尾;
(4) 由(3)可知后序遍历数组从后往前生成,则递归时先递归右子树,再递归左子树。

代码如下:

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
constexpr auto N = 30;

using namespace std;

int inOrder[N], preOrder[N], postOrder[N];
int stk[N] = { 0 };
int pre_ptr, in_ptr, post_ptr;
int stk_ptr = 0;

void push(int num);
int pop();
void readTraversal(int stack[], int cnt);
void traversalAgain(int inOrder[], int preOrder[], int len);

int main() {
	int nodeNum;
	cin >> nodeNum;
	pre_ptr = in_ptr = 0;
	post_ptr = N - 1;
	readTraversal(stk, nodeNum);
	traversalAgain(inOrder, preOrder, nodeNum);

    //后序遍历序列时从后往前生成,则第一个有效值的下标为N-nodeNum
	for (int i = N - nodeNum; i < N - 1; i++) {
		printf("%d ", postOrder[i]);
	}
	printf("%d", postOrder[N - 1]);
	return 0;
}

void readTraversal(int stk[], int cnt) {
	cnt = 2 * cnt;
	int tmp;
	while (cnt--) {
		string str;
		cin >> str;
		if (!str.compare("Pop")) {
			tmp = pop();
			inOrder[in_ptr++] = tmp;
		}
		else {
			cin >> tmp;
			push(tmp);
			preOrder[pre_ptr++] = tmp;
		}
	}
}

void push(int num) {
	stk[stk_ptr++] = num;
}

int pop() {
	return stk[--stk_ptr];
}

void traversalAgain(int inOrder[], int preOrder[], int len) {
	if (len == 0) return; /*对应子树为空的情况,保证函数能正常退出*/
	postOrder[post_ptr--] = preOrder[0]; //将先序遍历序列首值(根节点)传入后续遍历序列中
	int rootIdx = 0;//每次递归中将根节点清零,以找到该层递归中子树的根节点下标
	for (; rootIdx < len; rootIdx++)//找寻当前树根节点下标
		if (inOrder[rootIdx] == preOrder[0]) {
			break;
		}
	traversalAgain(inOrder + rootIdx + 1, preOrder + rootIdx + 1, len - rootIdx - 1);//递归右子树
	traversalAgain(inOrder, preOrder + 1, rootIdx);//递归左子树
}

测试结果:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值