A1086. 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.
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.
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
1 #include<cstdio> 2 #include<iostream> 3 #include<stack> 4 #include<string.h> 5 using namespace std; 6 typedef struct NODE{ 7 NODE* left, *right; 8 int data; 9 }node; 10 stack<int> stk; 11 int pre[31], in[31], N; 12 node* create(int preL, int preR, int inL, int inR){ 13 if(preL > preR){ 14 return NULL; 15 } 16 node *root = new node; 17 root->data = pre[preL]; 18 int i; 19 for(i = inL; i <= inR; i++) 20 if(in[i] == root->data) 21 break; 22 int Lnum = i - inL; 23 root->left = create(preL + 1, preL + Lnum, inL, i - 1); 24 root->right = create(preL + Lnum + 1, preR, i + 1, inR); 25 return root; 26 } 27 void post(node *tree, int &cnt){ 28 if(tree == NULL) 29 return; 30 post(tree->left, cnt); 31 post(tree->right, cnt); 32 if(cnt == N - 1) 33 printf("%d", tree->data); 34 else{ 35 printf("%d ", tree->data); 36 cnt++; 37 } 38 } 39 40 int main(){ 41 int num, indexPre = 0, indexIn = 0; 42 char str[5]; 43 scanf("%d", &N); 44 for(int i = 0; i < 2*N; i++){ 45 scanf("%s", str); 46 if(strcmp(str, "Push") == 0){ 47 scanf("%d ", &num); 48 stk.push(num); 49 pre[indexPre++] = num; 50 }else{ 51 num = stk.top(); 52 stk.pop(); 53 in[indexIn++] = num; 54 } 55 } 56 node *tree = create(0, N - 1, 0, N - 1); 57 int cnt = 0; 58 post(tree, cnt); 59 cin >> N; 60 return 0; 61 }
总结:
1、中序遍历的非递归实现:不断将非空的左孩子入栈,当左边为空时,弹出一个栈顶元素访问之,并将指针移至他的右子树,继续进行开始时的操作。 在这个过程中,push的特点是不断把遇到的新节点push入栈,因此push的过程就是先序遍历的过程。而pop自然是中序的过程。因此,中序与先序的非递归实现的区别就在于访问节点的时机不同,先序在push时,中序在pop时。
2、因此可以根据题目同时建立一个栈,同步做push和pop操作,先得到先序与中序遍历序列,再按照套路建树。