C++ 二叉树遍历实现
- 原文:http://blog.csdn.net/nuaazdh/article/details/7032226
- //二叉树遍历
- //作者:nuaazdh
- //时间:2011年12月1日
- #include<stdio.h>
- #include<stdlib.h>
- //二叉树结点结构
- typedef struct BiTNode{
- char ch; //结点数据
- struct BiTNode *lchild; //左孩子
- struct BiTNode *rchild; //右孩子
- }BiTNode,*BiTree;
- void AddBiTree(BiTree ,BiTNode *);//创建二叉树
- void PreOrderTraverse(BiTNode *); //前序遍历
- void InOrderTraverse(BiTNode *); //中序遍历
- void PostOrderTraverse(BiTNode *); //后序遍历
- void main()
- {
- char ch;//结点数据
- BiTree T,p;//树T,和临时树p
- printf("请输入结点内容(以空格未结束标识):");
- scanf("%c",&ch);//读入用户输入
- T=NULL;
- while(ch!=' '){//判断输入
- //创建新结点
- if(p=(BiTNode *)malloc(sizeof(BiTNode))){
- p->ch = ch;
- p->lchild = NULL;
- p->rchild = NULL;
- }
- else
- {
- printf("内存分配出错.\n");
- exit(0);
- }
- if(T==NULL)
- T=p;
- else
- AddBiTree(T,p);
- scanf("%c",&ch);//读入用户输入
- }
- //输出遍历结果
- printf("前序遍历:\n");
- PreOrderTraverse(T);
- printf("\n中序遍历:\n");
- InOrderTraverse(T);
- printf("\n后序遍历:\n");
- PostOrderTraverse(T);
- }
- //创造二叉树
- void AddBiTree(BiTree T,BiTree p)
- {
- if((p->ch <= T->ch)&&(T->lchild!=NULL))
- AddBiTree(T->lchild,p);
- else if((p->ch <= T->ch)&&(T->lchild==NULL))
- T->lchild=p;
- else if(T->rchild!=NULL)
- AddBiTree(T->rchild,p);
- else T->rchild=p;
- }
- //前序遍历
- void PreOrderTraverse(BiTree T)
- {
- if(T){
- printf("%c ",T->ch);
- PreOrderTraverse(T->lchild);
- PreOrderTraverse(T->rchild);
- }
- }
- //中序遍历
- void InOrderTraverse(BiTree T)
- {
- if(T){
- InOrderTraverse(T->lchild);
- printf("%c ",T->ch);
- InOrderTraverse(T->rchild);
- }
- }
- //后序遍历
- void PostOrderTraverse(BiTree T)
- {
- if(T){
- PostOrderTraverse(T->lchild);
- PostOrderTraverse(T->rchild);
- printf("%c ",T->ch);
- }
- }
原文:http://blog.csdn.net/oohaha_123/article/details/25902697
二叉树的非递归遍历
最近看书上说道要掌握二叉树遍历的6种编写方式,之前只用递归方式编写过,这次就用非递归方式编写试一试。
C++编程练习(8)----“二叉树的建立以及二叉树的三种遍历方式“(前序遍历、中序遍历、后续遍历)
递归的思想也就是栈的思想,既然不用递归,那就改用栈的方式。
“递归=栈”
1、前序遍历
前序遍历按照“根结点-左孩子-右孩子”的顺序进行访问。
a)递归实现前序遍历:
- void PreOrderTraverse(BiTNode *T) /*递归前序遍历*/
- {
- if (T==NULL)
- return;
- std::cout<<T->data<<"\t";
- PreOrderTraverse(T->lchild);
- PreOrderTraverse(T->rchild);
- }
b)非递归实现前序遍历:
对于根结点P:
1)访问结点P,并将结点P入栈;
2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P;
3)直到P为NULL并且栈为空,则遍历结束。
- void nPreOrderTraverse(BiTNode *T) /*非递归前序遍历*/
- {
- if (T==NULL)
- return;
- BiTNode *p;
- p = T;
- std::stack<BiTNode*> stk;
- while(p!=NULL||!stk.empty())
- {
- while(p!=NULL)
- {
- std::cout<<p->data<<"\t";
- stk.push(p);
- p = p->lchild;
- }
- if(!stk.empty())
- {
- p = stk.top();
- stk.pop();
- p = p->rchild;
- }
- }
- }
2、中序遍历
中序遍历按照“左孩子-根结点-右孩子”的顺序进行访问。
a)递归实现中序遍历
- void InOrderTraverse(BiTNode *T) /*递归中序遍历*/
- {
- if (T==NULL)
- return;
- InOrderTraverse(T->lchild);
- std::cout<<T->data<<"\t";
- InOrderTraverse(T->rchild);
- }
b)非递归实现中序遍历
对于根结点P:
1)若其左孩子不为空,则将P入栈并将P的左孩子置为当前的P,然后对当前结点P再进行相同的处理;
2)若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将当前的P置为栈顶结点的右孩子;
3)直到P为NULL并且栈为空则遍历结束。
- void nInOrderTraverse(BiTNode *T) /*非递归中序遍历*/
- {
- if(T==NULL)
- return;
- std::stack<BiTNode*> stk;
- BiTNode* p;
- p = T;
- while(p!=NULL || !stk.empty())
- {
- while(p!=NULL)
- {
- stk.push(p);
- p = p->lchild;
- }
- if(!stk.empty())
- {
- p = stk.top();
- stk.pop();
- std::cout<<p->data<<"\t";
- p = p->rchild;
- }
- }
- }
3、后序遍历
后序遍历按照“左孩子-右孩子-根结点”的顺序进行访问。
a)递归实现后序遍历
- void PostOrderTraverse(BiTNode *T) /*递归后序遍历*/
- {
- if(T==NULL)
- return;
- PostOrderTraverse(T->lchild);
- PostOrderTraverse(T->rchild);
- std::cout<<T->data<<"\t";
- }
b)非递归实现后序遍历
要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。
对于根结点P:
1)将P入栈,设置当前结点 cur ;
2)将当前的 cur 置为栈顶结点,如果 cur 不存在左孩子和右孩子,或者 cur 存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则可以直接访问该结点并进行出栈操作。否则将 cur 的右孩子和左孩子依次入栈;
3)直到栈为空则遍历结束。
- void nPostOrderTraverse(BiTNode *T) /*非递归后序遍历*/
- {
- if(T==NULL)
- return;
- BiTNode* cur; /*当前结点*/
- BiTNode* pre = NULL; /*前一次输出的结点*/
- std::stack<BiTNode*> stk;
- stk.push(T);
- while(!stk.empty())
- {
- cur = stk.top();
- if((cur->lchild==NULL && cur->rchild==NULL) ||
- (pre!=NULL && (cur->lchild==pre || cur->rchild==pre)))
- { /*如果当前结点没有孩子结点或者孩子节点都已被访问过*/
- std::cout<<cur->data<<"\t";
- stk.pop();
- pre = cur;
- }
- else
- {
- if(cur->rchild!=NULL)
- stk.push(cur->rchild);
- if(cur->lchild!=NULL)
- stk.push(cur->lchild);
- }
- }
- }
4、完整测试代码
1)BiTree.h头文件
- /* BiTree.h头文件 */
- #include<iostream>
- #include<stack>
- typedef char TElemType;
- class BiTNode{ /*创建结点类,使用的是左右孩子表示法*/
- public:
- BiTNode():data(0),lchild(NULL),rchild(NULL){}
- TElemType data;
- BiTNode *lchild,*rchild;
- };
- void CreateBiTree(BiTNode **T) /*二叉树的建立,这里形参用的是双指针,需要注意*/
- { /*这里输入的是一个扩展二叉树,每个结点若有空指针,*/
- TElemType ch; /*则将其值设为一个特定值,本代码中是'#'*/
- std::cin>>ch;
- std::cin.clear();
- if(ch=='#')
- *T=NULL;
- else
- {
- *T=new BiTNode;
- if(!*T)
- exit(1);
- (*T)->data=ch;
- CreateBiTree(&(*T)->lchild);
- CreateBiTree(&(*T)->rchild);
- }
- }
- void PreOrderTraverse(BiTNode *T) /*递归前序遍历*/
- {
- if (T==NULL)
- return;
- std::cout<<T->data<<"\t";
- PreOrderTraverse(T->lchild);
- PreOrderTraverse(T->rchild);
- }
- void nPreOrderTraverse(BiTNode *T) /*非递归前序遍历*/
- {
- if (T==NULL)
- return;
- BiTNode *p;
- p = T;
- std::stack<BiTNode*> stk;
- while(p!=NULL||!stk.empty())
- {
- while(p!=NULL)
- {
- std::cout<<p->data<<"\t";
- stk.push(p);
- p = p->lchild;
- }
- if(!stk.empty())
- {
- p = stk.top();
- stk.pop();
- p = p->rchild;
- }
- }
- }
- void InOrderTraverse(BiTNode *T) /*递归中序遍历*/
- {
- if (T==NULL)
- return;
- InOrderTraverse(T->lchild);
- std::cout<<T->data<<"\t";
- InOrderTraverse(T->rchild);
- }
- void nInOrderTraverse(BiTNode *T) /*非递归中序遍历*/
- {
- if(T==NULL)
- return;
- std::stack<BiTNode*> stk;
- BiTNode* p;
- p = T;
- while(p!=NULL || !stk.empty())
- {
- while(p!=NULL)
- {
- stk.push(p);
- p = p->lchild;
- }
- if(!stk.empty())
- {
- p = stk.top();
- stk.pop();
- std::cout<<p->data<<"\t";
- p = p->rchild;
- }
- }
- }
- void PostOrderTraverse(BiTNode *T) /*递归后序遍历*/
- {
- if(T==NULL)
- return;
- PostOrderTraverse(T->lchild);
- PostOrderTraverse(T->rchild);
- std::cout<<T->data<<"\t";
- }
- void nPostOrderTraverse(BiTNode *T) /*非递归后序遍历*/
- {
- if(T==NULL)
- return;
- BiTNode* cur; /*当前结点*/
- BiTNode* pre = NULL; /*前一次输出的结点*/
- std::stack<BiTNode*> stk;
- stk.push(T);
- while(!stk.empty())
- {
- cur = stk.top();
- if((cur->lchild==NULL && cur->rchild==NULL) ||
- (pre!=NULL && (cur->lchild==pre || cur->rchild==pre)))
- { /*如果当前结点没有孩子结点或者孩子节点都已被访问过*/
- std::cout<<cur->data<<"\t";
- stk.pop();
- pre = cur;
- }
- else
- {
- if(cur->rchild!=NULL)
- stk.push(cur->rchild);
- if(cur->lchild!=NULL)
- stk.push(cur->lchild);
- }
- }
- }
2)main文件
- #include"BiTree.h"
- using namespace std;
- int main()
- {
- BiTNode *T=new BiTNode;
- std::cout<<"请前序遍历输入各节点:";
- CreateBiTree(&T);
- cout<<"\n该树的前序遍历输出为:"<<endl;
- PreOrderTraverse(T);
- cout<<endl;
- nPreOrderTraverse(T);
- cout<<"\n该树的中序遍历输出为:"<<endl;
- InOrderTraverse(T);
- cout<<endl;
- nInOrderTraverse(T);
- cout<<"\n该树的后序遍历输出为:"<<endl;
- PostOrderTraverse(T);
- cout<<endl;
- nPostOrderTraverse(T);
- cout<<endl;
- return 0;
- }
5、测试结果
C++ 二叉树遍历实现的更多相关文章
- python实现二叉树遍历算法
说起二叉树的遍历,大学里讲的是递归算法,大多数人首先想到也是递归算法.但作为一个有理想有追求的程序员.也应该学学非递归算法实现二叉树遍历.二叉树的非递归算法需要用到辅助栈,算法着实巧妙,令人脑洞大开. ...
- 【二叉树遍历模版】前序遍历&&中序遍历&&后序遍历&&层次遍历&&Root->Right->Left遍历
[二叉树遍历模版]前序遍历 1.递归实现 test.cpp: 12345678910111213141516171819202122232425262728293031323334353637 ...
- hdu 4605 线段树与二叉树遍历
思路: 首先将所有的查询有一个vector保存起来.我们从1号点开始dfs这颗二叉树,用线段树记录到当前节点时,走左节点的有多少比要查询该节点的X值小的,有多少大的, 同样要记录走右节点的有多少比X小 ...
- poj2255 (二叉树遍历)
poj2255 二叉树遍历 Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & %llu Descripti ...
- D - 二叉树遍历(推荐)
二叉树遍历问题 Description Tree Recovery Little Valentine liked playing with binary trees very much. Her ...
- 二叉树遍历 C#
二叉树遍历 C# 什么是二叉树 二叉树是每个节点最多有两个子树的树结构 (1)完全二叉树——若设二叉树的高度为h,除第 h 层外,其它各层 (1-h-1) 的结点数都达到最大个数,第h层有叶子结点,并 ...
- 二叉树——遍历篇(递归/非递归,C++)
二叉树--遍历篇 二叉树很多算法题都与其遍历相关,笔者经过大量学习.思考,整理总结写下二叉树的遍历篇,涵盖递归和非递归实现. 1.二叉树数据结构及访问函数 #include <stdio.h&g ...
- 二叉树遍历(flist)(二叉树,已知中序层序,求先序)
问题 C: 二叉树遍历(flist) 时间限制: 1 Sec 内存限制: 128 MB提交: 76 解决: 53[提交][状态][讨论版][命题人:quanxing][Edit] [TestDat ...
- 二叉树遍历(flist)(已知中序和按层遍历,求先序 )
问题 F: 二叉树遍历(flist) 时间限制: 1 Sec 内存限制: 128 MB提交: 11 解决: 9[提交][状态][讨论版][命题人:quanxing][Edit] [TestData ...
随机推荐
- 通过VMware Tools 将主机windows的目录共享给linux虚拟机
之前有写过 本地虚拟机挂载windows共享目录搭建开发环境 这篇,里面讲通过使用samba来实现网络共享 最近发现其实完全不用这么麻烦,VMware tools就可以帮助我们轻松的共享文件夹 这里引 ...
- 20151007kaggle Titanic心得
Titanic是kaggle上一个练手的比赛,kaggle平台提供一部分人的特征,以及是否遇难,目的是预测另一部分人是否遇难.目前抽工作之余,断断续续弄了点,成绩为0.79426.在这个比赛过程中,接 ...
- RHAS Linux下架构Lotus Domino详解(附视频)
此处下载操作视频:RHAS Linux下架构Lotus Domino 6.5视频教程 在rhas下架构Lotus Domino 汉化 650) this.width=650;" o ...
- android 运行 python
Jython is an implementation of the Python programming language designed to run on the Java platform. ...
- Nginx下Redmine2.6配置
Apache下Redmine2.6配置,请参考:http://blog.linuxeye.com/405.html CentOS6.6下安装Redmine2.6+MySQL5.6+Nginx,教程如下 ...
- Apache Spark 架构
1.Driver:运行 Application 的 main() 函数并且创建 SparkContext. 2.Client:用户提交作业的客户端. 3.Worker:集群中任何可以运行 Applic ...
- 移动端页面的head头部内容
- UVA 11983 Weird Advertisement(线段树求矩形并的面积)
UVA 11983 题目大意是说给你N个矩形,让你求被覆盖k次以上的点的总个数(x,y<1e9) 首先这个题有一个转化,吧每个矩形的x2,y2+1这样就转化为了求N个矩形被覆盖k次以上的区域的面 ...
- Spring JTA应用JOTM & Atomikos I Application
关于Spring JTA的介绍非常多了,这里就不再一再阐述其优越性怎么怎么了,直接开始正题.一个大致的需求如下,用户在进行增删改操作时,会同时更新2至3个数据库的数据表,操作需要事务来包裹,以便在操作 ...
- 创建类模式(四):原型(Prototype)
定义 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 原型模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建 ...