编程题 03-树3 Tree Traversals Again【PAT】
文章目录
- 题目
- 输入格式
- 输出格式
- 输入样例
- 输出样例
- 题解
- 解题思路
- 完整代码
编程练习题目集目录
题目
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 1 1 to 6 6 6) is traversed, the stack operations are: push( 1 1 1); push( 2 2 2); push( 3 3 3); pop(); pop(); push( 4 4 4); pop(); pop(); push( 5 5 5); push( 6 6 6); pop(); pop(). Then a unique binary tree (shown in Figure 1 1 1) can be generated from this sequence of operations. Your task is to give the postorder traversal sequence of this tree.
![]() |
---|
Figure 1 |
输入格式
Each input file contains one test case. For each case, the first line contains a positive integer N ( ≤ 30 ) N (≤30) N(≤30) which is the total number of nodes in a tree (and hence the nodes are numbered from 1 1 1 to N N N). Then 2 N 2N 2N lines follow, each describes a stack operation in the format: “Push X X X” where X X X is the index of the node being pushed onto the stack; or “Pop” meaning to pop one node from the stack.
输出格式
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.
输入样例
6
Push 1
Push 2
Push 3
Pop
Pop
Push 4
Pop
Pop
Push 5
Push 6
Pop
Pop
输出样例
3 4 2 6 5 1
题解
解题思路
入栈是前序遍历,弹出是中序遍历,输出要求后续遍历。
完整代码
#include<iostream>
#include<string>
#include<vector>
#include<stack>using namespace std;// 递归函数:通过前序和中序遍历构造后序遍历
// 参数: preOrder:前序遍历数组 preL:前序遍历子数组起点 inOrder:中序遍历数组 nL:中序遍历子数组起点
// postOrder:后序遍历结果数组(引用传递) postL:后序遍历子数组起点 n:当前子树节点数量
void getPostOrder(vector<int> preOrder, int preL, vector<int> inOrder, int inL, vector<int> &postOrder, int postL, int n)
{if (n == 0) return ; // 递归终止条件:空树if (n == 1) { // 叶子节点直接写入后序遍历postOrder[postL] = preOrder[preL];return ;}auto root = preOrder[preL]; // 根节点 = 前序遍历的第一个元素postOrder[postL + n - 1] = root; // 后序遍历的根节点总是在最后int i = 0; // 在中序数组中定位根节点位置while (i < n) {if (inOrder[inL + i] == root) break;++i;}int leftSize = i; // 左子树大小int rightSize = n - i - 1; // 右子树大小// 递归处理左子树// 前序数组:从preL+1开始,长度为leftSize 中序数组:从inL开始,长度为leftSize 后序数组:从postL开始,长度为leftSizegetPostOrder(preOrder, preL + 1, inOrder, inL, postOrder, postL, leftSize);// 递归处理右子树// 前序数组:从preL+leftSize+1开始,长度为rightSize 中序数组:从inL+leftSize+1开始,长度为rightSize 后序数组:从postL+leftSize开始,长度为rightSizegetPostOrder(preOrder, preL + leftSize + 1, inOrder, inL + leftSize + 1, postOrder, postL + leftSize, rightSize);
}// 模拟构造树的前序和中序遍历数组
vector<vector<int>> getOrder(int N)
{vector<int> preOrder(N, 0); // 前序遍历数组vector<int> inOrder(N, 0); // 中序遍历数组stack<int> stack; // 辅助栈int preIndex = 0, inIndex = 0; // 索引指针for (int i = 0; i < 2*N; ++i) { // 处理2N次操作string op; int val;cin >> op;if (op == "Push") { // 入栈操作(对应前序遍历)cin >> val;preOrder[preIndex++] = val; // 记录前序遍历stack.push(val); // 元素入栈} else if (op == "Pop") { // 出栈操作(对应中序遍历)inOrder[inIndex++] = stack.top(); // 记录中序遍历stack.pop(); // 元素出栈}}return {preOrder, inOrder}; // 返回前序和中序遍历数组
}int main(void)
{int N;cin >> N;auto traversal = getOrder(N); // 获取前序和中序遍历数组vector<int> preOrder = traversal[0];vector<int> inOrder = traversal[1];vector<int> postOrder(N, 0); // 初始化后序遍历数组getPostOrder(preOrder, 0, inOrder, 0, postOrder, 0, N);for (int i = 0; i < N; ++i) { // 输出后序遍历结果cout << postOrder[i];if (i < N-1) cout << " ";}cout << endl;return 0;
}