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:

  1. Push
  2. Push
  3. Push
  4. Pop
  5. Pop
  6. Push
  7. Pop
  8. Pop
  9. Push
  10. Push
  11. Pop
  12. Pop

Sample Output:

可以使用堆栈以非递归方式实现顺序二进制树遍历。你的任务是给出这棵树的后序遍历序列。

每个输入文件包含一个测试用例。对于每种情况,第一行包含正整数N(≤ 3 0),它是节点的总数量在树(并且因此节点编号从1到N)。然后接下来是N行,每行描述一种堆栈操作,格式为:“Push X”,其中X是被推入堆栈的节点的索引; 或“Pop”表示从堆栈中弹出一个节点。

对于每个测试用例,在一行中打印相应树的后序遍历序列。保证存在解决方案。所有数字必须用一个空格分隔,并且在行的末尾不能有额外的空格。

先给出大神的思路

对二叉树的中序遍历可以通过使用栈来避免迭代的方法,对于figure1中的6节点树而言,它的栈操作为push(1); push(2); push(3); pop(); pop(); push(4); pop(); pop(); push(5); push(6); pop(); pop()。依据这个输入可以生成这个二叉树,要求打印出该树的后序遍历。

解法:

该题要求我们通过中序遍历的栈实现的栈操作来生成二叉树。

如上图,中序遍历的操作流程(其中箭头代表遍历流),我们可以看出:

1.每次push都指向一个新的节点。

2.每次pop都指向一个被抛出的节点。

3.连续的pop-pop或push-push流的方向都相同。

4.连续的push-pop指向同一个叶节点,同时执行方向转弯。(节点3)

5.连续的pop-push经过一个父节点,同时执行方向转弯。(节点2)

6.每个节点只能pop指向一次,push指向一次。(节点4到2直接跳到1)

于是我们就可以通过这些特性来构建二叉树:

1.读入第一次push构建根节点,根节点入栈。

2.读入下一个操作,有两种情况:

(1)push

说明有一个新节点出现,构建一个节点。如果上次操作为push,把该节点设为栈顶的左儿子,节点入栈。如果上次是pop,经过一个父节点,说明应该是生成了父节点的一个儿子,所以将该节点设为上次pop出来的节点的右儿子。

(2)pop

说明正在pop一个节点,不论上次操作是,该次都抛出一个节点。

这是我写的,有点菜

  1. #include <iostream>
  2. #include <stack>
  3. #include <string>
  4. #include <algorithm>
  5. #define MaxTree 31
  6. #define Null -1
  7. using namespace std;
  8.  
  9. int P[MaxTree];
  10. int num=;
  11. int NUM=;
  12. stack<int> st;
  13.  
  14. struct TreeNode
  15. {
  16. int date;
  17. int Left;
  18. int Right;
  19. }T[MaxTree];
  20.  
  21. int BuildTree(struct TreeNode T[])
  22. {
  23. int N,m,p,i;
  24. string str,pre;
  25. int Root;
  26. cin>>N;
  27. for(i=;i<*N;i++)
  28. {
  29. cin>>str;
  30. if(str=="Push")
  31. {
  32. cin>>m;
  33. if(i==)
  34. {
  35. Root=;
  36. T[num].date=m;
  37. T[num].Left=Null;
  38. T[num].Right=Null;
  39. st.push(num);
  40. pre=str;
  41. }
  42. else if(pre=="Push")
  43. {
  44. T[num].Left=num+;
  45. num++;
  46. T[num].date=m;
  47. T[num].Left=Null;
  48. T[num].Right=Null;
  49. st.push(num);
  50. pre=str;
  51. }
  52. else if(pre=="Pop")
  53. {
  54. T[p].Right=num+;
  55. num++;
  56. T[num].date=m;
  57. T[num].Left=Null;
  58. T[num].Right=Null;
  59. st.push(num);
  60. pre=str;
  61. }
  62. }
  63. else if(str=="Pop")
  64. {
  65. p=st.top();
  66. st.pop();
  67. pre=str;
  68. }
  69. }
  70. if(N==)
  71. {
  72. Root=Null;
  73. }
  74. return Root;
  75. }
  76.  
  77. void search(int Tree)
  78. {
  79. if(Tree==Null)
  80. return;
  81. search(T[Tree].Left);
  82. search(T[Tree].Right);
  83. P[NUM++]=T[Tree].date;
  84. }
  85.  
  86. int main()
  87. {
  88. int Tree;
  89. Tree=BuildTree(T);
  90. search(Tree);
  91. int i;
  92. for(i=;i<NUM;i++)
  93. {
  94. if(i==)
  95. cout<<P[i];
  96. else
  97. cout<<' '<<P[i];
  98. }
  99. return ;
  100. }

下面是别人用动态链表实现的,值得一看

  1. #include <cstdio>
  2. #include <stack>
  3. using namespace std;
  4.  
  5. int preorder[], inorder[];
  6. int n, preid = , inid = , cnt = ;
  7. int get(){
  8. char s[];
  9. scanf("%s", s);
  10. if (s[] == 'o') return -;
  11. int a;
  12. scanf("%d", &a);
  13. return a;
  14. }
  15. void build(int preb, int pree, int inb, int ine){
  16. if (preb > pree) return;
  17. int root = preorder[preb];
  18. int inroot = inb;
  19. while (inorder[inroot] != root) ++inroot;
  20. build(preb+, preb+inroot-inb, inb, inroot-);
  21. build(preb+inroot-inb+, pree, inroot+, ine);
  22. if (cnt++ != ) putchar(' ');
  23. printf("%d", root);
  24. }
  25. int main(){
  26. scanf("%d", &n);
  27. stack<int> st;
  28. for (int i = ; i < n*; ++i){
  29. int a = get();
  30. if (a != -){
  31. st.push(a);
  32. preorder[preid++] = a;
  33. }else{
  34. inorder[inid++] = st.top();
  35. st.pop();
  36. }
  37. }
  38. build(, n-, , n-);
  39. return ;
  40. }
  1. #include <string>
  2. #include <iostream>
  3. #include <stack>
  4. using namespace std;
  5.  
  6. const string PUSH("Push");
  7. const string POP("Pop");
  8.  
  9. typedef struct Node
  10. {
  11. int data;
  12. Node* left;
  13. Node* right;
  14. Node(int d):data(d), left(NULL), right(NULL){}
  15. }Node;
  16.  
  17. void PostOrderTraverse(Node *root)
  18. {
  19. Node* temp = root;
  20. Node* pre = NULL;
  21. stack<Node*> S;
  22. int flag = ;
  23.  
  24. while(temp || !S.empty())
  25. {
  26. if(temp)
  27. {
  28. S.push(temp);
  29. temp = temp->left;
  30. }
  31. else
  32. {
  33. temp = S.top();
  34. if(temp->right && temp->right != pre)
  35. temp = temp->right;
  36. else
  37. {
  38. if(!flag)
  39. {
  40. flag = ;
  41. cout<< temp->data;
  42. }
  43. else
  44. cout<<" "<<temp->data;
  45. S.pop();
  46. pre = temp;
  47. temp = NULL;
  48. }
  49. }
  50. }
  51. cout<<endl;
  52. }
  53.  
  54. int main()
  55. {
  56. int n, data;
  57. string act;
  58. stack<Node*> S;
  59. Node* root = NULL, *pre = NULL;
  60. int l = , r = ;
  61. cin >> n;
  62.  
  63. //First, build the tree , root of tree is *root.
  64. for(int i=; i <= *n; i++)
  65. {
  66. Node* temp;
  67. cin >> act;
  68. if(act == PUSH)
  69. {
  70. cin >> data;
  71. temp = new Node(data);
  72. if(i == )
  73. {
  74. root = temp;
  75. }
  76.  
  77. S.push(temp);
  78. if(pre)
  79. {
  80. if(l == )
  81. pre->left = temp;
  82. else
  83. pre->right = temp;
  84. }
  85. l = ;
  86. pre = temp;
  87. }
  88. else if(act == POP)
  89. {
  90. pre = S.top();
  91. S.pop();
  92. l = ;
  93. }
  94. }
  95.  
  96. PostOrderTraverse(root);
  97.  
  98. system("pause");
  99. return ;
  100. }

Tree Traversals Again的更多相关文章

  1. Tree Traversals

    Tree Traversals 原题链接 常见的二叉树遍历的题目,根据后序遍历和中序遍历求层次遍历. 通过后序遍历和中序遍历建立起一棵二叉树,然后层序遍历一下,主要难点在于树的建立,通过中序遍历和后序 ...

  2. HDU 1710 二叉树的遍历 Binary Tree Traversals

    Binary Tree Traversals Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/O ...

  3. hdu1710(Binary Tree Traversals)(二叉树遍历)

    Binary Tree Traversals Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/O ...

  4. HDU1710Binary Tree Traversals

    HDU1710Binary Tree Traversals 题目大意:给一个树的前序遍历和中序遍历,要求输出后序遍历. (半年前做这道题做了两天没看懂,今天学了二叉树,回来AC了^ ^) 首先介绍一下 ...

  5. HDU-1701 Binary Tree Traversals

    http://acm.hdu.edu.cn/showproblem.php?pid=1710 已知先序和中序遍历,求后序遍历二叉树. 思路:先递归建树的过程,后后序遍历. Binary Tree Tr ...

  6. 03-树2. Tree Traversals Again (25)

    03-树2. Tree Traversals Again (25) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue ...

  7. HDU 1710-Binary Tree Traversals(二进制重建)

    Binary Tree Traversals Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/O ...

  8. PAT1086:Tree Traversals Again

    1086. Tree Traversals Again (25) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue ...

  9. Binary Tree Traversals(HDU1710)二叉树的简单应用

    Binary Tree Traversals Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/O ...

  10. 【PAT】1020 Tree Traversals (25)(25 分)

    1020 Tree Traversals (25)(25 分) Suppose that all the keys in a binary tree are distinct positive int ...

随机推荐

  1. ADO.Net中DataSet的应用

    一.知识点描述 1.DataSet是ADO.NET的中心概念.可以把DataSet当成内存中的数据库,DataSet是不依赖于数据库的独立数据集合.也就是说,即使断开数据链路,或者关闭数据库,Data ...

  2. IDEA 自动生成Hibernate实体类和Mapping文件

    一.新建工程Demo(如果选的时候勾选了hibernate,IDEA会自动下载Hibernate包,不需要手动导入) 二.导入相关包 Mysql && Hibernate 三.添加Hi ...

  3. ubuntu编译安装opencv

    简易安装opencv2: conda install --channel https://conda.anaconda.org/menpo opencv 或: sudo apt-get install ...

  4. UITableView(自定义cell)试水心得

    初次试水自定义cell的UITableView 实现目标      最终实现结果   界面复原度:98% 未能完全复刻的地方:下半部分的tableview与头部的控件间距上的误差 原因:在做table ...

  5. 微信小程序上传后发布或者体验版测试无数据解决办法

    在做微信小程序开发的过程中,发现小程序在本地调用接口的数据都显示,但是上传之后,发现手机体验没有数据.以下为解决办法: 1.先清除缓存试试. 2.打开微信小程序工具右上角的详情——项目设置,将“不校验 ...

  6. Redis的使用原理

    原理介绍 (1)什么是redis? Redis 是一个基于内存的高性能key-value数据库. (有空再补充,有理解错误或不足欢迎指正) (2)Reids的特点 Redis本质上是一个Key-Val ...

  7. hbuilder中的wap2app (将M站快速转换成App的开发框架)使用过程有关原生标题的关闭

    首先,我最近在做有关将M站快速转换成App的项目,在网上看了很多,最终结合同学的推荐,我选择了hbuilder,有关于hbuilder的下载还有具体使用方法,官网都有详细的说明,我就不介绍了,我重点介 ...

  8. 关于修改banner信息;nginx反向代理apache应用

    本周实验 1. Linux下Apache部署一个php页面,返回http数据包中查看server信息,修改Apache 配置使server banner自定义. 2. nginx设置反向代理,代理上面 ...

  9. LeetCode - Robot Room Cleaner

    Given a robot cleaner in a room modeled as a grid. Each cell in the grid can be empty or blocked. Th ...

  10. Android Studio学习之 日志工具

    Log.v()   低级日志 Log.d(' ',' ')  debug调试信息 第一个参数tag,当前类名 第二个参数msg,打印具体内容 Log.i()  info数据 Log.w() warn警 ...