1086. 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) 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 PopSample Output:
3 4 2 6 5 1
题目要求通过栈操作来建树,看似题目只给出了中序遍历的结果(出栈顺序),其实仔细观察可以发现压栈顺序就是先序遍历,因此题目给出了先序序列和中序序列,使用中序序列和任一其他序列就可以重新建立树,原理在于,通过先序从前到后处理或者后序从后到前处理都可以得到根结点的编号,通过这个编号,在中序序列中找到后,左侧就是左子树、右侧就是右子树。
本题给出了先序序列和中序序列,因此从前到后遍历先序序列,每次从中序序列中找到左子树和右子树范围,用left和right标记,进行递归,如果left!=right,说明当前结点不是叶子结点,继续递归左右子树,如果left=right,说明子树长度为1,也就是叶子结点。
需要注意的是,读取带空格的行需要getline,如果cin和getline混用,会使得getline多读一个空行,因此全部使用getline读取,使用stringstream实现字符串和数字的转换。
判断命令时,只需要判断第二个字符,如果第二个字符是u,说明是Push操作,从第5个位置开始截串就可以拿到数字。
代码如下:
#include <iostream> #include <stdio.h> #include <vector> #include <string> #include <sstream> #include <stack> using namespace std; int N,cur; vector<int> preOrder; vector<int> inOrder; typedef struct TreeNode *Node; struct TreeNode{ int num; Node left,right; TreeNode(){ left = NULL; right = NULL; } }; int findRootIndex(int rootNum){ for(int i = 0;i < N; i++){ if(inOrder[i] == rootNum){ return i; } } return -1; } Node CreateTree(int left, int right){ if(left > right) return NULL; int root = preOrder[cur]; cur++; int rootIndex = findRootIndex(root); Node T = new TreeNode(); T->num = root; if(left != right){ T->left = CreateTree(left,rootIndex-1); T->right = CreateTree(rootIndex+1,right); } return T; } bool firstOutPut = true; void PostOrder(Node T){ if(!T) return; PostOrder(T->left); PostOrder(T->right); if(firstOutPut){ printf("%d",T->num); firstOutPut = false; }else{ printf(" %d",T->num); } } int main() { stringstream ss; string Nstr; getline(cin,Nstr); ss << Nstr; ss >> N; ss.clear(); string input; stack<int> stk; int value; for(int i = 0; i < N * 2; i++){ getline(cin,input); if(input[1] == 'u'){ string num = input.substr(5); ss << num; ss >> value; ss.clear(); stk.push(value); preOrder.push_back(value); }else{ value = stk.top(); stk.pop(); inOrder.push_back(value); } } Node T = CreateTree(0,N-1); PostOrder(T); return 0; }