二叉树遍历的非递归算法
大一下半期数据结构
知识点
递归算法虽然简单,但一般而言,其执行效率并不高。对于二叉树的遍历操作,可以仿照递归算法执行过程中工作栈的状态变化得到非递归算法。
一、前序遍历非递归算法
二叉树前序遍历非递归算法的关键是:在前序遍历过某结点的整个左子树后,如何找到该结点的右子树的根指针,对于图一二叉树
工作栈S和当前根指针bt的变化情况以及树中各结点的访问次序。
分析二叉树前序遍历的执行过程可以看出,在访问某结点后,应将该结点的指针保存在栈中,以便以后能通过它找到
该结点的右子树。一般情况下,在前序遍历中,设要遍历二叉树的根指针为bt,可能有两种情况:
(1)若bt!=NULL,则表明当前二叉树不为空,此时,应输出根结点bt的值并将bt保存到栈中,准备继续遍历bt的
左子树。
(2)若bt==NULL,则表明以bt为根指针的二叉树遍历完毕,并且bt是栈顶指针所指结点的左子树。若栈不为空,应根据栈顶指针所指结点找到待遍历右子树的根指针并赋予bt,以继续遍历下去:若栈为空,则表明整个二叉树遍历完毕,应结束。
二叉树前序遍历的非递归算法
void PreorderTraversal( BiNode *root )//( BinTree BT )BinTree 为结构体指针,BiNode 为结构体类型//二叉链表的根指针root
{BiNode *bt=root,*S[MaxSize];//定义顺序栈,工作指针bt初始化int top=-1;//初始化顺序栈while(bt!=NULL||top!=-1)//两个条件都不成立才退出循环{while(bt!=NULL)//当bt不空时循环{printf(" %c",bt->Data);//输出bt->dataS[++top]=bt;//将指针bt保存到栈中bt=bt->lchild;//遍历bt的左子树}if(top!=-1)如果栈S不空,则{bt=S[top--];//将栈顶元素弹出至btbt=bt->rchild;//准备遍历bt的右子树}}
}
void PreorderTraversal( BinTree BT )
{Stack s=CreateStack();//Push(s,BT); BinTree now=BT; if(now!=NULL) Push(s,now); while(!IsEmpty(s)){ now=Pop(s); printf(" %c",now->Data);if(now->Right!=NULL) Push(s,now->Right);if(now->Left!=NULL) Push(s,now->Left); }
}
中序遍历非递归算法
在中序遍历过程中遇到某结点不能立即访问它,而是将它压栈,等到它的左子树遍历完毕后,再从栈中弹出并访问之。
void InorderTraversal( BiNode *root )//( BinTree BT )BinTree 为结构体指针,BiNode 为结构体类型//二叉链表的根指针root
{BiNode *bt=root,*S[MaxSize];//定义顺序栈,工作指针bt初始化int top=-1;//初始化顺序栈while(bt!=NULL||top!=-1)//两个条件都不成立才退出循环{while(bt!=NULL)//当bt不空时循环{S[++top]=bt;//将指针bt保存到栈中bt=bt->lchild;//遍历bt的左子树}if(top!=-1)如果栈S不空,则{bt=S[top--];//将栈顶元素弹出至btprintf(" %c",bt->Data);//输出bt->databt=bt->rchild;//准备遍历bt的右子树}}
}
void InorderTraversal( BinTree BT )
{ Stack s=CreateStack();if(BT!=NULL) Push(s,BT);BinTree now; while(!IsEmpty(s)){ while(Peek(s)->Left!=NULL) Push(s,Peek(s)->Left); while(!IsEmpty(s)){ now=Peek(s); printf(" %c",now->Data); Pop(s); if(now->Right!=NULL){ Push(s,now->Right); break; } } }
}
后序遍历非递归算法
当遍历完左子树,由于右子树尚未遍历,因此栈顶结点不能出栈,通过栈顶结点找到它的右子树,准备遍历它的右子树:当遍历完右子树,将栈顶结点出栈,并访问它。
为了区别对栈顶结点的不同处理,设置标志变量flag,flag=1表示遍历完左子树,栈顶结点不能出栈:flag=2表示遍历完右子树,栈顶结点可以出栈并访问。可以用c语言中的结构体类型来定义栈元素类型
typedef struct{
BiNode *ptr;
int flag;
}ElemType;//BiNode 为结构体类型
设要遍历二叉树的根指针为bt,则有以下两种情况:
(1)若bt不等于NULL,则bt及标志flag(置为1)入栈,遍历其左子树。
(2)若bt等于NULL,此时栈为空,则整个遍历结束:若栈不为空,则表明栈顶结点的左子树或右子树已遍历完毕。若栈顶结点的标志flag=1,则表明栈顶结点的左子树以遍历完毕,将flag改为2,并遍历栈顶结点的右子树:若栈顶结点的标志flag=2,则表明栈顶结点的右子树也遍历完毕,出栈并输出栈顶结点。
void PostorderTraversal(BiNode *root )
{ElemType S[MaxSize];//定义顺序栈int top=-1;初始化顺序栈BiNode *bt=root;//工作指针bt初始化while(bt!=NULL||top!=-1)//循环直到bt为空且栈S为空{while(bt!=NULL){top++;S[top].ptr=bt;//root连同标志flag入栈S[top].flag=1;bt=bt->lchild;//继续遍历bt的左子树}while(top!=-1&&S[top].flag==2)//注意是循环,可能连续出栈//当栈S非空且栈顶元素的标志为2时,出栈并输出栈顶结点{bt=S[top--].ptr;printf(" %c",bt->Data);}if(top!=-1)//当栈非空,将栈顶元素的标志改为2,准备遍历栈顶结点的右子树{S[top].flag=2;bt=S[top].ptr->rchild;}}}
void PostorderTraversal( BinTree BT )
{ Stack s=CreateStack();if(BT!=NULL) Push(s,BT); BinTree now=BT,last=NULL;while(!IsEmpty(s)){ while(Peek(s)->Left!=NULL) Push(s,Peek(s)->Left); while(!IsEmpty(s)){ now=Peek(s); if(now->Right==last||now->Right==NULL){ printf(" %c",now->Data);Pop(s);last=now;} else{ Push(s,now->Right); break; } } }
}
添加链接描述
附大神博客地址
二叉树遍历的非递归算法相关推荐
- [转载]二叉树先序、中序、后序三种遍历的非递归算法
本贴给出二叉树先序.中序.后序三种遍历的非递归算法,此三个算法可视为标准算法. 1.先序遍历非递归算法 #define maxsize 100 typedef struct { Bitree Elem ...
- 二叉树中序遍历的非递归算法
根据二叉树的先序遍历结果创建一棵二叉树,即先创建根结点,然后再创建左子树,最后创建右子树,对于左右子树的创建也遵循根左右的原则,所以对于左右子树的创建可以递归调用本函数,此问题是典型的需要用递归算法求 ...
- 数据结构 | 二叉树 先根、中根、后根遍历的非递归算法
上期文章: 数据结构 | 树与二叉树 参考教材:<数据结构>,刘大有 编程语言: C++ 目录 (一)二叉树的存储结构 (二)二叉树的遍历 先根遍历非递归算法 中根遍历非递归算法 后根遍历 ...
- 二叉树后序遍历的非递归算法
二叉树的后序遍历的非递归算法与二叉树的先序和中序遍历的非递归算法相比稍微复杂一点. 大致思路是:如果当前结点左右子树均为空,则可以访问当前结点,或者左右子树不均为空,但是前一个访问的结点是当前结点的左 ...
- 后序遍历的非递归算法python_二叉树后序遍历(递归与非递归)算法C语言实现...
二叉树后序遍历的实现思想是:从根节点出发,依次遍历各节点的左右子树,直到当前节点左右子树遍历完成后,才访问该节点元素. 图 1 二叉树 如图 1 中,对此二叉树进行后序遍历的操作过程为: 从根节点 1 ...
- 二叉树利用堆栈实现遍历的非递归算法
二叉树的遍历有三种不同的遍历方法,分别是前序遍历.中序遍历以及后序遍历 遍历的实现我们在上一篇博客中已经用递归的方法实现了,那么可不可以不用递归实现呢,答案是可以的 在这一篇博客中我们会利用堆栈将遍历 ...
- java使用btree_java数据结构之二叉树遍历的非递归实现
算法概述 递归算法简洁明了.可读性好,但与非递归算法相比要消耗更多的时间和存储空间.为提高效率,我们可采用一种非递归的二叉树遍历算法.非递归的实现要借助栈来实现,因为堆栈的先进后出的结构和递归很相似. ...
- 漫谈二叉树遍历(非递归)
------这篇文章旨在提出一种简单方便,易于理解时空复杂度低且风格统一的二叉树非递归遍历方法. 从二叉树先序遍历开始 二叉树的先序遍历(非递归)相比中后序是最少花哨.最统一的.一般来说先序遍历的代码 ...
- 二叉树遍历(非递归)
文章目录 二叉树遍历非递归版本 前序遍历 中序遍历 后序遍历 层序遍历 层序遍历+map记录高度 二叉树遍历非递归版本 前序遍历 如果右侧不为空,则右侧进栈,随后是左侧进栈.因为栈是先进后出,所以实现 ...
最新文章
- 浅谈使用openwave测试的几个注意项
- Visual Studio 2010生成SQL Server测试数据
- linux shell base64 加解密 编码字符串
- [转]php curl 设置host curl_setopt CURLOPT_HTTPHEADER 指定host
- SpringBoot配置嵌入式Servlet容器
- sql获取oracle数据库数据,通过sql语句获取数据库的基本信息
- 中国人工智能学会通讯——基于视频的行为识别技术 1.7 视频的深度分段网络...
- 最优化学习笔记(十)——对偶线性规划
- Java Spring 异常处理
- 编译原理--运行时存储组织(自己看)
- Kalman Filter—Data Fusion, Covarince Matrix, State Space Representation, Observation
- ie工具internet选项安全自定义级别java_activex控件被禁止怎么办
- 远程桌面连接,凭据问题
- 迅雷“去中心化”再升级 转型中All in 区块链
- xml-rpc是个什么东东?
- TCP/IP协议(2):各层网络设备
- 考研逻辑整理 - 负判断、联言判断和联言推理
- Docker安装报错Hardware assisted virtualization and data execution protection must be enabled in the BIOS
- Ardupilot-链接汇总
- High-speed Charting Control(MFC绘图控件)--MFC绘图Demo(包含鼠标响应)
热门文章
- 理解 TCP(二):报文结构 1
- linux下的nginx+tomcat配置
- Android无线安全测试工具-WiFinSpect
- 给那些因为Firebug而舍不得FireFox的朋友
- YAF 关闭错误异常使用trigger_error来处理
- Android系统匿名共享内存(Anonymous Shared Memory)C++调用接口分析(7)
- vector中resize()和reserve()区别
- 堆栈用数组和用链表实现
- Python中的变量、引用、拷贝和作用域
- Codeforces Round #430 D. Vitya and Strange Lesson