1086. Tree Traversals Again (树的遍历,前序中序转后序)

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.
1086. Tree Traversals Again (树的遍历,前序中序转后序)

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

题目大意:用栈的形式给出一棵二叉树的建立的顺序,求这棵二叉树的后序遍历

 

需要一个堆结构s,一个child变量(表示该节点是其父亲节点的左孩子还是右孩子),父亲节点fa
对于push v操作:
1).第一个push肯定是根节点root。
2).根据child变量,建立fa与v的父子关系。
3).由于是中序遍历,所以接下来的节点必定是v的left(如果有的话),child=left,fa=v;
4).然后进行push操作

对于pop操作:
1).根据中序遍历性质,可知接下来的节点必定是pop节点的右孩子(如果有的话),child=right,fa=s.top()
2).进行pop操作。

#include<iostream>
#include<algorithm>
#include<string.h>
#include<stack>
#define LEFT 0
#define RIGHT 1
#define maxn 100
using namespace std;
stack<int> s;
//着重注意这题考查的是"建树"的技巧 
struct  NODE
{
   int left=-1;	
   int right=-1;	 
}node[maxn];

bool first=true;
void postOrder(int u){//虽然建树时是按中序建的树
    if(u==-1)         //但是按后序扫的
        return;
    postOrder(node[u].left);
    postOrder(node[u].right);
    if(first){
        first=false;
        printf("%d",u);
    }
    else{
        printf(" %d",u);
    }
}

int main()
{
	int n,v;
	int root=-1,fa;
	//fa是为了记录当前结点
	//以便把各个node结点相连 
	int child=LEFT;
	//child变量记录的是,
	//当前父节点往左走,还是往右走 
	char str[10];
	scanf("%d",&n);
	while(scanf("%s",str)!=EOF)
	{
		if(strcmp(str,"Push")==0)
		{
			scanf("%d",&v);
			if(root==-1)//为这棵树找根节点,入口 
			root=v;
			else 
			{
				if(child==LEFT)
                node[fa].left=v;
				else node[fa].right=v;				
			}
			fa=v;//更新父节点 
			child=LEFT;
			s.push(v); 
		}//对于入栈的操作,
		 //由于是中序,新节点优先进左子树 
		else//出栈后在改变方向,
		    //再次push时向右子树push 
		{
			child=RIGHT;
			fa=s.top(); 
			s.pop();
		}
	}
	postOrder(root);
    return 0;	
}