【树】7-5Tree 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 (≤) which is the total number of nodes in a tree (and hence the nodes are numbered from 1 to N). Then 2 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
思路:
- 通过观察可知入栈顺序即先序遍历,出栈顺序即中序遍历,所以在得知先序和中序遍历的基础上还原树,然后对该树进行后序遍历。
- 其中,为了得到先序(中序)结果,对每一条命令进行判断,如果第二个字符是“u”说明是“push”,然后从第五个位置开始截取就可获得数字,同时将该数字入栈;否则是“pop”,将栈中的数字出栈。
- 在得到先序和中序序列之后,从前往后遍历先序序列,每次从中序序列中找到左右子树的范围,使用left和right标记,进行递归,如果left!=right,说明当前结点不是叶子结点,继续递归左右子树;如果left==right,说明该结点是叶子结点。
- 注意,其中的两个变量cur和printtag必须设成全局变量,因为使用该变量的函数中有递归函数,如果cur设成局部变量会发生段错误;如果printtag设成局部变量,会发生输出格式错误。
解题思路和代码参考https://blog.csdn.net/xyt8023y/article/details/47443489
1 #include <iostream> 2 #include <cstdlib> 3 #include <vector> 4 #include <stack> 5 #include <string> 6 #include <sstream> 7 using namespace std; 8 9 //分别存储先序序列和中序序列 10 vector<int>preorder; 11 vector<int>inorder; 12 13 typedef struct TreeNode* Node; 14 struct TreeNode 15 { 16 int num; 17 Node left; 18 Node right; 19 }; 20 21 //根据结点值在中序序列中寻找根结点的下标位置 22 int FindRootIndex(int rootnum) { 23 for (unsigned int i = 0; i < inorder.size(); i++) { 24 if (inorder[i] == rootnum) 25 return i; 26 } 27 return -1; 28 } 29 30 //通过给出中序序列中左右子树的范围建树 31 int cur;//定义遍历preorder的变量 32 Node CreateTree(int left, int right) { 33 //int cur = 0; 34 if (left > right) 35 return NULL; 36 int rootnum = preorder[cur]; 37 cur++; 38 int rootIndex = FindRootIndex(rootnum); 39 //建立该根结点 40 Node T = (Node)malloc(sizeof(TreeNode)); 41 T->num = rootnum; 42 T->left = NULL; 43 T->right = NULL; 44 if (left != right) { 45 T->left = CreateTree(left, rootIndex - 1); 46 T->right = CreateTree(rootIndex + 1, right); 47 } 48 return T; 49 } 50 51 52 //后序遍历 53 int printtag = 0; 54 void PostTraver(Node T) { 55 //int printtag = 0; 56 if (T) { 57 PostTraver(T->left); 58 PostTraver(T->right); 59 if (!printtag) { 60 cout << T->num; 61 printtag = 1; 62 } 63 else 64 cout << " " << T->num; 65 } 66 } 67 68 int main() { 69 int n; 70 stack<int>s; 71 cin >> n; 72 getchar(); 73 for (int i = 0; i < n*2; i++) { 74 string str; 75 getline(cin, str); 76 77 if (str[1] == 'u') { 78 int num = stoi(str.substr(5)); 79 preorder.push_back(num); 80 s.push(num); 81 } 82 else { 83 int num = s.top(); 84 s.pop(); 85 inorder.push_back(num); 86 } 87 } 88 Node T = CreateTree(0,inorder.size()-1); 89 PostTraver(T); 90 return 0; 91 }