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.
可以用栈实现二叉树的非递归中序遍历。例如,假设当一个6结点二叉树(有从1到6的编号)被遍历时,栈的操作是:push(1); push(2); push(3); pop(); pop() push(4); pop(); pop(); push(5); push(6); pop(); pop()。 然后可以从该操作序列生成唯一的二叉树(如图1所示)。 你的任务是给出这棵树的后序遍历序列。
Figure 1
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.
每个输入文件包含一个测试用例。 每个用例中,第一行包含树中的节点的总数正整数N(N<=30,因此节点从1编号到N)。 接下来的2N行,每行按照格式描述一个堆栈操作:“Push X”,X是被推到堆栈上的节点的索引; 或“Pop”,意味着从堆栈中弹出一个节点。
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
思路:
因为要用到栈,所以先给出头文件#include <stack>中的函数:
#include <stack>
using namespace std;
int main()
{
stack<int> s; //定义一个stack变量,且定义时已经初始化
s.empty();//栈空返回1,不空返回0
s.push(1);//入栈
s.pop();//出栈
int t=s.top();//获取栈顶元素
int num=s.size();//获取栈的元素个数
}
经过观察输入可以看出,Push的顺序是1,2,3,4,5,6,是先序遍历的顺序;Pop的顺序为3,2,4,1,6,5,是中序遍历的顺序。
因此,我们首先就可以根据入栈和出栈的顺序,确定先序序列和中序序列。然后根据上图的方法,递归的使用相同的方法求出后序序列。
#include <iostream>
#include <string.h>
#include <stack>
using namespace std;
#define MaxSize 30
int preOrder[MaxSize];
int inOrder[MaxSize];
int postOrder[MaxSize];
void Solve(int preL,int inL,int postL,int n);
int main()
{
for(int i=0;i<MaxSize;i++)//初始化
{
preOrder[i] = 0;
inOrder[i] = 0;
postOrder[i] = 0;
}
stack<int> inputStack;//根据输入的Push和Pop建立起来的栈
int nodeNum;//结点总数
scanf("%d\n",&nodeNum);
int data;
int preIndex=0,inIndex=0,postIndex=0;//下标初始化
int countspace=0;//输出时的空格计数
char str[5];//字符串,存放输入的Push或Pop
char inStack[]="Push";
char outStack[]="Pop";
for(int i=0;i<2*nodeNum;i++)
{
scanf("%s",str);
if(strcmp(str,inStack)==0)//在C语言中,字符的比较可以直接用等号,但字符串的比较要用strcmp(s1,s2)函数
{ // 输入Push时,data放入先序序列数组
scanf("%d\n",&data);
preOrder[preIndex++]=data;
inputStack.push(data);
}else if(strcmp(str,outStack)==0){//输入Pop时 ,pop出的元素放入中序序列数组
inOrder[inIndex++]=inputStack.top();
inputStack.pop();
}
}
Solve(0,0,0,nodeNum);
for(int i=0;i<nodeNum;i++)
{
if(countspace++!=0)
{
printf(" ");
}
printf("%d",postOrder[i]);
}
return 0;
}
void Solve(int preL,int inL,int postL,int n)
{ //前3个参数分别表示先、中、后序列下的树的第一个数的下标 ,最后一个表示树的结点数
if(n==0)
{
return;
}
if(n==1)
{
postOrder[postL]=preOrder[preL];
return;
}
int root=preOrder[preL];
postOrder[postL+n-1]=root;
int LeftNodeNum,RightNodeNum;
for(int i=0;i<n;i++)
{
if(inOrder[inL+i]==root)
{
LeftNodeNum=i;//左子树结点数
break;
}
}
RightNodeNum=n-LeftNodeNum-1;//右子树结点数
Solve(preL+1,inL,postL,LeftNodeNum);//左子树
Solve(preL+LeftNodeNum+1,inL+LeftNodeNum+1,postL+LeftNodeNum,RightNodeNum);//右子树
}