03-树3 Tree Traversals Again (25 分)
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.

Figure 1
Input Specification:
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 to NNN). Then 2N2N2N 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
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXN 30
#define OK 1
#define ERROR 0
int pre[MAXN], in[MAXN], post[MAXN];
//定义栈结构
struct SNode {
int data;
struct SNode *next;
};
typedef struct SNode *Stack;
//创建一个栈
Stack CreateStack() {
Stack S;
S = (Stack)malloc(sizeof(struct SNode));
if(S) S->next = NULL;
return S;
}
//判断栈是否为空
int IsStackEmpty(Stack S) {
return S->next == NULL;
}
//入栈
void Push(Stack S, int data) {
Stack p;
p = CreateStack();
p->data = data;
p->next = S->next;
S->next = p;
}
//出栈
int Pop(Stack S, int *result) {
Stack p = S->next;
if (IsStackEmpty(S)) return ERROR;
*result = p->data;
S->next = p->next;
free(p);
return OK;
}
//获取字符串中的数字
int GetInputNum(char input[]) {
int result = 0, i, temp;
for (i = 3; i < strlen(input); i++) {
if (input[i] >= '0' && input[i] <= '9') {
temp = (int)(input[i] - '0');
result = result * 10 + temp;
}
}
return result;
}
//解题函数
//构造post序列
//preL为pre数组起始下标
//inL为in数组起始下标
//postL为post数组起始下标
//n为总节点个数
void Solve(int preL, int inL, int postL, int n) {
//root为根结点数据,L为左子树节点个数,R为右子树节点个数
int root, i, L, R;
if (n == 0) return;
if (n == 1) {
post[postL] = pre[preL];
return;
}
//根结点数据为pre数组第一个元素的数据
root = pre[preL];
//post数组最后一个元素应为根节点的数据
post[postL + n - 1] = root;
//在in数组找到与根节点数据相同的元素下标
for (i = 0; i < n; i++)
if (in[inL + i] == root)
break;
L = i;
R = n - L - 1;
//对左子树求解
//左子树pre数组起始位置应为根节点后一个位置(preL+1)
//左子树in数组起始位置为根结点左侧,因此起始位置不变(inL)
//左子树数据应在post数组最前面,因此起始位置不变(postL)
//左子树总节点数为L
Solve(preL + 1, inL, postL, L);
//对右子树求解
//右子树pre数组起始位置应为左子树最后一个元素的下一个位置(preL+L+1)
//右子树in数组起始位置为根结点右侧,而根结点左侧有L个左子树的元素,因此确定位置(inL+L+1)
//右子树数据应在post数组L个左子树部分的后一个位置(postL+L)
//右子树总节点数为R
Solve(preL + L + 1, inL + L + 1, postL + L, R);
}
//根据post数组输出结果
void PrintResult(int n) {
int i;
for (i = 0; i < n; i++) {
if (i == 0) printf("%d", post[i]);
else printf(" %d", post[i]);
}
printf("\n");
}
int main(void) {
char input[100] = "\0", temp[100] = "\0";
int N, i, preCount = 0, inCount = 0, popResult, num;
Stack S = CreateStack();
i = scanf("%d\n", &N);
for (i = 0; i < 2 * N; i++) {
gets_s(input);
strncpy(temp, input, 3);
temp[3 - 1] = 0;
//入栈
if (!strcmp(temp, "Pus")) {
num = GetInputNum(input);
Push(S, num);
pre[preCount] = num;
preCount++;
}
//出栈
if (!strcmp(temp, "Pop")) {
Pop(S, &popResult);
in[inCount] = popResult;
inCount++;
}
}
Solve(0, 0, 0, N);
PrintResult(N);
return 0;
}