【树】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.
输入格式:
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.
输出格式:
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
解题思路:
- 入栈的顺序为树的先序遍历,出栈的顺序为树的中序遍历,相当于已知先序遍历和中序遍历求后序遍历序列。
- 思路1:直接利用递归求解后序遍历序列;思路2:先建树,再后序遍历。
本程序采用思路1。
注意:
IsFull 函数和 IsEmpty 函数中需要传参,小心遗漏。
完整程序:
/*
【解题思路】
1.入栈的顺序为树的先序遍历,出栈的顺序为树的中序遍历,相当于已知先序遍历和中序遍历求后序遍历序列
2.思路1:直接利用递归求解后序遍历序列;思路2:先建树,再后序遍历
本程序采用思路1
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MaxSize 30
#define true 1
#define false 0
typedef struct SNode {
int *data;
int top; // 栈顶指针,空栈为-1
int maxSize;
} *Stack;
int pre[MaxSize],in[MaxSize],post[MaxSize]; // 分别存放先序、中序序列和后序序列
Stack CreateStack(); // 创建栈
void Push(Stack S,int ele); // 入栈
int Pop(Stack S); // 出栈
int IsFull(Stack S); // 判断栈满
int IsEmpty(Stack S); // 判断栈空
void PostOrder(int preL,int inL,int postL,int n); // 由先序遍历和中序遍历序列得到后序遍历序列
int main()
{
Stack S;
int i,N; // N为结点个数,因为每个结点被push一次pop一次,所以之后会有2 * N行输入
int pj = 0,ij = 0; // pj为pre数组的下标,ij为in数组的下标
char str[10]; // 临时存放"Push"或"Pop"的字符数组
int e; // 结点元素
S = CreateStack();
scanf("%d",&N);
getchar(); // 读取缓存区的回车符
for(i = 0;i < 2 * N;i ++) {
scanf("%s",str); // 输入空白字符结束
if(strcmp(str,"Push") == 0) {
scanf("%d",&e);
getchar();
pre[pj ++] = e;
Push(S,e);
}
else {
in[ij ++] = Pop(S);
}
}
PostOrder(0,0,0,N);
for(i = 0;i < N -1;i ++) {
printf("%d ",post[i]);
}
printf("%d",post[i]);
return 0;
}
Stack CreateStack()
{
Stack S = (Stack)malloc(sizeof(struct SNode));
S -> data = (int *)malloc(MaxSize * sizeof(int));
S -> top = -1;
S -> maxSize = MaxSize;
return S;
}
int IsFull(Stack S)
{
if(S -> top == S -> maxSize -1)
return true; // 栈满
else
return false;
}
int IsEmpty(Stack S)
{
if(S -> top == -1)
return true;
else
return false;
}
void Push(Stack S,int ele)
{
if(!IsFull(S)) // 注意别忘记参数
S -> data[++ (S -> top)] = ele;
else
return;
}
int Pop(Stack S)
{
if(!IsEmpty(S)) // 注意别忘记参数
return (S -> data[(S -> top) --]);
else
return false;
}
void PostOrder(int preL,int inL,int postL,int n) // preL:pre数组的最左项;inL:in数组的最左项;postL:post数组的最左项;n:结点数
{
int i,L,R;
int root; // 树根结点
if(n == 0) return;
if(n == 1) {
post[postL] = pre[preL];
return;
}
root = pre[preL]; // pre数组的最左项就是树根结点
post[postL + n - 1] = root;
for(i = 0;i < n;i ++)
if(in[inL + i] == root) break;
L = i; // 左子树结点数
R = n - L - 1; // 右子树结点数
PostOrder(preL + 1,inL,postL,L); // 左子树递归
PostOrder(preL + L + 1,inL + L + 1,postL + L,R); // 右子树递归
}