1. 原文:http://blog.csdn.net/nuaazdh/article/details/7032226
  2. //二叉树遍历
  3. //作者:nuaazdh
  4. //时间:2011年12月1日
  5. #include<stdio.h>
  6. #include<stdlib.h>
  7. //二叉树结点结构
  8. typedef struct BiTNode{
  9. char ch;            //结点数据
  10. struct BiTNode *lchild;        //左孩子
  11. struct BiTNode *rchild;        //右孩子
  12. }BiTNode,*BiTree;
  13. void AddBiTree(BiTree ,BiTNode *);//创建二叉树
  14. void PreOrderTraverse(BiTNode *); //前序遍历
  15. void InOrderTraverse(BiTNode *);   //中序遍历
  16. void PostOrderTraverse(BiTNode *);  //后序遍历
  17. void main()
  18. {
  19. char ch;//结点数据
  20. BiTree T,p;//树T,和临时树p
  21. printf("请输入结点内容(以空格未结束标识):");
  22. scanf("%c",&ch);//读入用户输入
  23. T=NULL;
  24. while(ch!=' '){//判断输入
  25. //创建新结点
  26. if(p=(BiTNode *)malloc(sizeof(BiTNode))){
  27. p->ch = ch;
  28. p->lchild = NULL;
  29. p->rchild = NULL;
  30. }
  31. else
  32. {
  33. printf("内存分配出错.\n");
  34. exit(0);
  35. }
  36. if(T==NULL)
  37. T=p;
  38. else
  39. AddBiTree(T,p);
  40. scanf("%c",&ch);//读入用户输入
  41. }
  42. //输出遍历结果
  43. printf("前序遍历:\n");
  44. PreOrderTraverse(T);
  45. printf("\n中序遍历:\n");
  46. InOrderTraverse(T);
  47. printf("\n后序遍历:\n");
  48. PostOrderTraverse(T);
  49. }
  50. //创造二叉树
  51. void AddBiTree(BiTree T,BiTree p)
  52. {
  53. if((p->ch <= T->ch)&&(T->lchild!=NULL))
  54. AddBiTree(T->lchild,p);
  55. else if((p->ch <= T->ch)&&(T->lchild==NULL))
  56. T->lchild=p;
  57. else if(T->rchild!=NULL)
  58. AddBiTree(T->rchild,p);
  59. else T->rchild=p;
  60. }
  61. //前序遍历
  62. void PreOrderTraverse(BiTree T)
  63. {
  64. if(T){
  65. printf("%c ",T->ch);
  66. PreOrderTraverse(T->lchild);
  67. PreOrderTraverse(T->rchild);
  68. }
  69. }
  70. //中序遍历
  71. void InOrderTraverse(BiTree T)
  72. {
  73. if(T){
  74. InOrderTraverse(T->lchild);
  75. printf("%c ",T->ch);
  76. InOrderTraverse(T->rchild);
  77. }
  78. }
  79. //后序遍历
  80. void PostOrderTraverse(BiTree T)
  81. {
  82. if(T){
  83. PostOrderTraverse(T->lchild);
  84. PostOrderTraverse(T->rchild);
  85. printf("%c ",T->ch);
  86. }
  87. }

原文:http://blog.csdn.net/oohaha_123/article/details/25902697

二叉树的非递归遍历

最近看书上说道要掌握二叉树遍历的6种编写方式,之前只用递归方式编写过,这次就用非递归方式编写试一试。

C++编程练习(8)----“二叉树的建立以及二叉树的三种遍历方式“(前序遍历、中序遍历、后续遍历)

递归的思想也就是栈的思想,既然不用递归,那就改用栈的方式。

“递归=栈”

1、前序遍历

前序遍历按照“根结点-左孩子-右孩子”的顺序进行访问。

a)递归实现前序遍历:

  1. void PreOrderTraverse(BiTNode *T)   /*递归前序遍历*/
  2. {
  3. if (T==NULL)
  4. return;
  5. std::cout<<T->data<<"\t";
  6. PreOrderTraverse(T->lchild);
  7. PreOrderTraverse(T->rchild);
  8. }

b)非递归实现前序遍历:

对于根结点P:
1)访问结点P,并将结点P入栈;
2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P;
3)直到P为NULL并且栈为空,则遍历结束。

  1. void nPreOrderTraverse(BiTNode *T)  /*非递归前序遍历*/
  2. {
  3. if (T==NULL)
  4. return;
  5. BiTNode *p;
  6. p = T;
  7. std::stack<BiTNode*> stk;
  8. while(p!=NULL||!stk.empty())
  9. {
  10. while(p!=NULL)
  11. {
  12. std::cout<<p->data<<"\t";
  13. stk.push(p);
  14. p = p->lchild;
  15. }
  16. if(!stk.empty())
  17. {
  18. p = stk.top();
  19. stk.pop();
  20. p = p->rchild;
  21. }
  22. }
  23. }

2、中序遍历

中序遍历按照“左孩子-根结点-右孩子”的顺序进行访问。

a)递归实现中序遍历

  1. void InOrderTraverse(BiTNode *T)    /*递归中序遍历*/
  2. {
  3. if (T==NULL)
  4. return;
  5. InOrderTraverse(T->lchild);
  6. std::cout<<T->data<<"\t";
  7. InOrderTraverse(T->rchild);
  8. }

b)非递归实现中序遍历

对于根结点P:
1)若其左孩子不为空,则将P入栈并将P的左孩子置为当前的P,然后对当前结点P再进行相同的处理;
2)若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将当前的P置为栈顶结点的右孩子;
3)直到P为NULL并且栈为空则遍历结束。

  1. void nInOrderTraverse(BiTNode *T)   /*非递归中序遍历*/
  2. {
  3. if(T==NULL)
  4. return;
  5. std::stack<BiTNode*> stk;
  6. BiTNode* p;
  7. p = T;
  8. while(p!=NULL || !stk.empty())
  9. {
  10. while(p!=NULL)
  11. {
  12. stk.push(p);
  13. p = p->lchild;
  14. }
  15. if(!stk.empty())
  16. {
  17. p = stk.top();
  18. stk.pop();
  19. std::cout<<p->data<<"\t";
  20. p = p->rchild;
  21. }
  22. }
  23. }

3、后序遍历

后序遍历按照“左孩子-右孩子-根结点”的顺序进行访问。

a)递归实现后序遍历

  1. void PostOrderTraverse(BiTNode *T)  /*递归后序遍历*/
  2. {
  3. if(T==NULL)
  4. return;
  5. PostOrderTraverse(T->lchild);
  6. PostOrderTraverse(T->rchild);
  7. std::cout<<T->data<<"\t";
  8. }

b)非递归实现后序遍历

这里实现略复杂,当初想出来的方法过于笨重,后参考http://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html,改写如下:

要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。

对于根结点P:

1)将P入栈,设置当前结点 cur ;

2)将当前的 cur 置为栈顶结点,如果 cur 不存在左孩子和右孩子,或者 cur 存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则可以直接访问该结点并进行出栈操作。否则将 cur 的右孩子和左孩子依次入栈;

3)直到栈为空则遍历结束。

  1. void nPostOrderTraverse(BiTNode *T)     /*非递归后序遍历*/
  2. {
  3. if(T==NULL)
  4. return;
  5. BiTNode* cur;       /*当前结点*/
  6. BiTNode* pre = NULL;        /*前一次输出的结点*/
  7. std::stack<BiTNode*> stk;
  8. stk.push(T);
  9. while(!stk.empty())
  10. {
  11. cur = stk.top();
  12. if((cur->lchild==NULL && cur->rchild==NULL) ||
  13. (pre!=NULL && (cur->lchild==pre || cur->rchild==pre)))
  14. {                               /*如果当前结点没有孩子结点或者孩子节点都已被访问过*/
  15. std::cout<<cur->data<<"\t";
  16. stk.pop();
  17. pre = cur;
  18. }
  19. else
  20. {
  21. if(cur->rchild!=NULL)
  22. stk.push(cur->rchild);
  23. if(cur->lchild!=NULL)
  24. stk.push(cur->lchild);
  25. }
  26. }
  27. }

4、完整测试代码

1)BiTree.h头文件

  1. /* BiTree.h头文件 */
  2. #include<iostream>
  3. #include<stack>
  4. typedef char TElemType;
  5. class BiTNode{                  /*创建结点类,使用的是左右孩子表示法*/
  6. public:
  7. BiTNode():data(0),lchild(NULL),rchild(NULL){}
  8. TElemType data;
  9. BiTNode *lchild,*rchild;
  10. };
  11. void CreateBiTree(BiTNode **T)      /*二叉树的建立,这里形参用的是双指针,需要注意*/
  12. {                                           /*这里输入的是一个扩展二叉树,每个结点若有空指针,*/
  13. TElemType ch;                               /*则将其值设为一个特定值,本代码中是'#'*/
  14. std::cin>>ch;
  15. std::cin.clear();
  16. if(ch=='#')
  17. *T=NULL;
  18. else
  19. {
  20. *T=new BiTNode;
  21. if(!*T)
  22. exit(1);
  23. (*T)->data=ch;
  24. CreateBiTree(&(*T)->lchild);
  25. CreateBiTree(&(*T)->rchild);
  26. }
  27. }
  28. void PreOrderTraverse(BiTNode *T)   /*递归前序遍历*/
  29. {
  30. if (T==NULL)
  31. return;
  32. std::cout<<T->data<<"\t";
  33. PreOrderTraverse(T->lchild);
  34. PreOrderTraverse(T->rchild);
  35. }
  36. void nPreOrderTraverse(BiTNode *T)  /*非递归前序遍历*/
  37. {
  38. if (T==NULL)
  39. return;
  40. BiTNode *p;
  41. p = T;
  42. std::stack<BiTNode*> stk;
  43. while(p!=NULL||!stk.empty())
  44. {
  45. while(p!=NULL)
  46. {
  47. std::cout<<p->data<<"\t";
  48. stk.push(p);
  49. p = p->lchild;
  50. }
  51. if(!stk.empty())
  52. {
  53. p = stk.top();
  54. stk.pop();
  55. p = p->rchild;
  56. }
  57. }
  58. }
  59. void InOrderTraverse(BiTNode *T)    /*递归中序遍历*/
  60. {
  61. if (T==NULL)
  62. return;
  63. InOrderTraverse(T->lchild);
  64. std::cout<<T->data<<"\t";
  65. InOrderTraverse(T->rchild);
  66. }
  67. void nInOrderTraverse(BiTNode *T)   /*非递归中序遍历*/
  68. {
  69. if(T==NULL)
  70. return;
  71. std::stack<BiTNode*> stk;
  72. BiTNode* p;
  73. p = T;
  74. while(p!=NULL || !stk.empty())
  75. {
  76. while(p!=NULL)
  77. {
  78. stk.push(p);
  79. p = p->lchild;
  80. }
  81. if(!stk.empty())
  82. {
  83. p = stk.top();
  84. stk.pop();
  85. std::cout<<p->data<<"\t";
  86. p = p->rchild;
  87. }
  88. }
  89. }
  90. void PostOrderTraverse(BiTNode *T)  /*递归后序遍历*/
  91. {
  92. if(T==NULL)
  93. return;
  94. PostOrderTraverse(T->lchild);
  95. PostOrderTraverse(T->rchild);
  96. std::cout<<T->data<<"\t";
  97. }
  98. void nPostOrderTraverse(BiTNode *T)     /*非递归后序遍历*/
  99. {
  100. if(T==NULL)
  101. return;
  102. BiTNode* cur;       /*当前结点*/
  103. BiTNode* pre = NULL;        /*前一次输出的结点*/
  104. std::stack<BiTNode*> stk;
  105. stk.push(T);
  106. while(!stk.empty())
  107. {
  108. cur = stk.top();
  109. if((cur->lchild==NULL && cur->rchild==NULL) ||
  110. (pre!=NULL && (cur->lchild==pre || cur->rchild==pre)))
  111. {                               /*如果当前结点没有孩子结点或者孩子节点都已被访问过*/
  112. std::cout<<cur->data<<"\t";
  113. stk.pop();
  114. pre = cur;
  115. }
  116. else
  117. {
  118. if(cur->rchild!=NULL)
  119. stk.push(cur->rchild);
  120. if(cur->lchild!=NULL)
  121. stk.push(cur->lchild);
  122. }
  123. }
  124. }

2)main文件

  1. #include"BiTree.h"
  2. using namespace std;
  3. int main()
  4. {
  5. BiTNode *T=new BiTNode;
  6. std::cout<<"请前序遍历输入各节点:";
  7. CreateBiTree(&T);
  8. cout<<"\n该树的前序遍历输出为:"<<endl;
  9. PreOrderTraverse(T);
  10. cout<<endl;
  11. nPreOrderTraverse(T);
  12. cout<<"\n该树的中序遍历输出为:"<<endl;
  13. InOrderTraverse(T);
  14. cout<<endl;
  15. nInOrderTraverse(T);
  16. cout<<"\n该树的后序遍历输出为:"<<endl;
  17. PostOrderTraverse(T);
  18. cout<<endl;
  19. nPostOrderTraverse(T);
  20. cout<<endl;
  21. return 0;
  22. }

5、测试结果

C++ 二叉树遍历实现的更多相关文章

  1. python实现二叉树遍历算法

    说起二叉树的遍历,大学里讲的是递归算法,大多数人首先想到也是递归算法.但作为一个有理想有追求的程序员.也应该学学非递归算法实现二叉树遍历.二叉树的非递归算法需要用到辅助栈,算法着实巧妙,令人脑洞大开. ...

  2. 【二叉树遍历模版】前序遍历&&中序遍历&&后序遍历&&层次遍历&&Root->Right->Left遍历

    [二叉树遍历模版]前序遍历     1.递归实现 test.cpp: 12345678910111213141516171819202122232425262728293031323334353637 ...

  3. hdu 4605 线段树与二叉树遍历

    思路: 首先将所有的查询有一个vector保存起来.我们从1号点开始dfs这颗二叉树,用线段树记录到当前节点时,走左节点的有多少比要查询该节点的X值小的,有多少大的, 同样要记录走右节点的有多少比X小 ...

  4. poj2255 (二叉树遍历)

    poj2255 二叉树遍历 Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu   Descripti ...

  5. D - 二叉树遍历(推荐)

    二叉树遍历问题 Description   Tree Recovery Little Valentine liked playing with binary trees very much. Her ...

  6. 二叉树遍历 C#

    二叉树遍历 C# 什么是二叉树 二叉树是每个节点最多有两个子树的树结构 (1)完全二叉树——若设二叉树的高度为h,除第 h 层外,其它各层 (1-h-1) 的结点数都达到最大个数,第h层有叶子结点,并 ...

  7. 二叉树——遍历篇(递归/非递归,C++)

    二叉树--遍历篇 二叉树很多算法题都与其遍历相关,笔者经过大量学习.思考,整理总结写下二叉树的遍历篇,涵盖递归和非递归实现. 1.二叉树数据结构及访问函数 #include <stdio.h&g ...

  8. 二叉树遍历(flist)(二叉树,已知中序层序,求先序)

    问题 C: 二叉树遍历(flist) 时间限制: 1 Sec  内存限制: 128 MB提交: 76  解决: 53[提交][状态][讨论版][命题人:quanxing][Edit] [TestDat ...

  9. 二叉树遍历(flist)(已知中序和按层遍历,求先序 )

    问题 F: 二叉树遍历(flist) 时间限制: 1 Sec  内存限制: 128 MB提交: 11  解决: 9[提交][状态][讨论版][命题人:quanxing][Edit] [TestData ...

随机推荐

  1. Apache Spark是什么?

    简单地说, Spark是发源于美国加州大学伯克利分校AMPLab的大数据分析平台,它立足于内存计算,从多迭代批量处理出发,兼顾数据仓库. 流处理和图计算等多种计算范式,是大数据系统领域的全栈计算平台. ...

  2. shell调试选项

    [shell调试选项] 一些常用选项的用法: -n 只读取shell脚本,但不实际执行 -x 进入跟踪方式,显示所执行的每一条命令 -c "string" 从strings中读取命 ...

  3. LeetCode104: Maximum Depth of Binary Tree

    Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along the long ...

  4. 原生JS修改标签样式为带阴影效果

    代码如下: JS部分 //点击时候,改变样式 function GetCategoryInfo(value) { var getInfo = value.toString().split(','); ...

  5. hdu 4115 Eliminate the Conflict ( 2-sat )

    Eliminate the Conflict Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/O ...

  6. CSU1612Destroy Tunnels(强连通)

    Destroy Tunnels 原来早忘记了离散里含有这么一个叫传递闭包的东西 矩阵A的闭包B = A U A^2 U A^3 U ... 所以这里直接如果A[i][j]!= 0,建边i->j跑 ...

  7. hdoj 5371 Hotaru's problem

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5371 这道题用到了Manacher算法,首先简单介绍一下Manacher算法: ----------- ...

  8. android Notification和NotificationManager的使用

    Notification和NotificationManager 1.Broadcast Receiver组件没有提供可视化的界面来显示广播信息.这里我们可以使用Notification和Notifi ...

  9. ActiveMQ简介与安装

    开源消息总线 支持JMS1.1和J2EE 1.4规范的 JMS Provider实现(持久化,XA消息,事务) 对Spring的支持,ActiveMQ可以很容易内嵌到使用Spring的系统里面去 支持 ...

  10. EasyUI ComboBox默认值

    combobox数据加载完后设置默认值 $('#ck').combobox({ url: '/External/GetAllCk', valueField: 'Ddbh', textField: 'D ...