本文已参与「新人创作礼」活动,一起开启掘金创作之路。
1576. 再次树遍历
原题传送:AcWing 1576. 再次树遍历
通过使用栈可以以非递归方式实现二叉树的中序遍历。
例如,假设遍历一个如下图所示的 节点的二叉树(节点编号从 到 )。
则堆栈操作为:push(1);push(2);push(3);pop();pop();push(4);pop();pop();push(5);push(6);pop();pop()。
我们可以从此操作序列中生成唯一的二叉树。
你的任务是给出这棵树的后序遍历。
输入格式
第一行包含整数 ,表示树中节点个数。
树中节点编号从 到 。
接下来 行,每行包含一个栈操作,格式为:
Push X,将编号为 的节点压入栈中。Pop,弹出栈顶元素。
输出格式
输出这个二叉树的后序遍历序列。
数据保证有解,数和数之间用空格隔开,末尾不能有多余空格。
数据范围
输入样例:
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
思路一:
Push为前序遍历,Pop为中序遍历,构造一棵树并保存后序遍历的序列。
题解一:
#include<bits/stdc++.h>
using namespace std;
const int N = 40;
int n, k1 = 0, k2 = 0;
stack<int> s;
int in[N], pre[N];
int post[N], cnt;
unordered_map<int, int> l, r, pos;
int build(int il, int ir, int pl, int pr)
{
int root = pre[pl];
int k = pos[root];
if(il < k)
l[root] = build(il, k - 1, pl + 1, pl + 1 + (k - 1 - il));
if(k < ir)
r[root] = build(k + 1, ir, pl + 1 + (k - 1 - il) + 1, pr);
post[cnt++] = root;
return root;
}
int main()
{
cin >> n;
for(int i = 0; i < n * 2; i++)
{
string t;
cin >> t;
if(t == "Push")
{
int num;
cin >> num;
s.push(num);
pre[k1++] = num;
}
else
{
int top = s.top();
in[k2] = top;
pos[in[k2]] = k2;
k2++;
s.pop();
}
}
build(0, n - 1, 0, n - 1);
cout << post[0];
for(int i = 1; i < n; i++)
cout << " " << post[i];
cout << endl;
return 0;
}
思路二:
对于所有的 Push ,除第一个Push是根结点,如果上一个是 Push ,说明当前这个点是上一个点的左儿子。如果上一个是 Pop ,说明当前这个点是上一个点的右儿子。
题解二:
#include<bits/stdc++.h>
using namespace std;
const int N = 40;
int n;
int l[N], r[N];
void dfs(int u, int root)
{
if(!u)
return;
dfs(l[u], root);
dfs(r[u], root);
cout << u;
if(u != root)
cout << " ";
}
int main()
{
cin >> n;
int root, last = 0, type;
stack<int> stk;
for(int i = 0; i < n * 2; i++)
{
string t;
cin >> t;
if(t == "Push")
{
int x;
cin >> x;
if(!last)
root = x;
else
{
if(type == 0)
l[last] = x;
else
r[last] = x;
}
stk.push(x);
last = x;
type = 0;
}
else
{
last = stk.top();
stk.pop();
type = 1;
}
}
dfs(root, root);
return 0;
}