二叉树遍历的非递归实现(java版)
来源:互联网 发布:网络信息有限公司名字 编辑:程序博客网 时间:2024/06/18 13:55
在前面的这篇文章中我写了二叉树遍历的递归实现,在这篇文章中我将讲述下二叉树的非递归实现。
大多数的递归问题的非递归算法,需要用栈来消除递归。栈是一种存储容器,同时又是一种控制结构,栈先进先出的控制结构,同时,调用时可用栈来保留必要的信息,退出时,可以从栈中取出信息,进行后续的处理。所以设计二叉树的遍历非递归算法, 需要用栈来保留节点的信息。
二叉树的结构
class Btree<T>{ T value; Btree<T> left; Btree<T> right; BNode(T obj, BNode<T> left, BNode<T> right){ this.value = obj; this.left = left; this.right = right; }}public void visitDate(Btree<T> root){ if (root != null) { System.out.println(root.value); } }
1.先序遍历二叉树的非递归实现
遍历思路:
(1).访问根节点,根节点入栈并进入其左子树,进而访问左子树的根节点并入栈,在进入下一层左子树,……,如此重复,直至当前节点为空。
(2).如栈非空,则从栈顶退出上一层的节点,并进入该节点的右子树。
代码如下:
public void preOder(Btree<T> root){ Stack<Btree<T>> stack = new Stack<Btree<T>>(); Btree<T> p = root;//保留当前的节点 while(p != null || !stack.isEmpty()){ //遍历这个节点的子节点,直到到达这个节点的叶子节点 while(p != null){ visitDate(p);//输出当前节点 stack.push(p);//把当前节点保存到堆栈中,以便遍历完左子树后遍历右子树 p = p.left; } } //最后一个叶子节点输出后,在栈中取该节点的根节点,遍历这个根节点的右孩子。 if (!stack.isEmpty()) { Btree<T> pop = stack.pop(); p = pop.right; } }
2.中序遍历二叉树的非递归实现
思路:
1.根节点入栈,进入其左子树,进而左子树的根节点入栈,进入下一层左子树,….,如此重复,直至当前节点为空·。
2.若栈非空,则退栈,访问出栈节点,并进入其右子树。
代码:
/* * 中根序遍历 */ public void midOrder(Btree<T> root){ Stack<Btree<T>> stack = new Stack<Btree<T>>(); Btree<T> p = root;//保存当前节点 while(p != null || !stack.isEmpty()){ if (p != null) { stack.push(p);//当前节点入栈 p = p.left;//遍历他的左节点 }else{ p = stack.pop();//当前节点为空,则取出栈顶元素, visitDate(p);//打印栈顶元素 p = p.right;//遍历该节点的右节点 } } }
3.后序遍历二叉树的非递归实现
思路:
1.根节点入栈,进入其左子树,进而左子树的根节点入栈,进入下一层左子树,……,如此重复,直至当前节点为空。
2.若栈非空,如果栈顶节点p的右子树为空,或者p的右孩子是刚访问的节点q,则退栈、访问p节点,并将p置为空,如果栈顶节点p有右子树且右子树为访问,则进入p的右子树。
我的代码:
/* * 后续遍历 */ public void lastOrder(Btree<T> root){ Stack<Btree<T>> stack = new Stack<Btree<T>>(); Btree<T> p = root;//保存当前节点 Btree<T> q = null;//记录最后一个输出的节点,用于检验是不是根节点的右节点 while(p != null || !stack.isEmpty()){ //由根节点向下遍历,知道找到该根节点下的最后一个叶子节点 while (p != null) { stack.push(p);//非叶子节点入栈 p = p.left;//指向该节点的左孩子 } //p为空,栈非空,说明遍历完了左孩子,处于叶子节点状态 if (!stack.isEmpty()) { p = stack.pop();//栈顶出栈 //因为如果该节点有右节点,肯定是先访问完右节点才开始访问跟节点的 //p.right == null:表示没有右节点,可以直接访问根节点 //p.right == q:刚访问完该节点右节点,则可以访问我该节点 if (p.right == null || p.right == q) { visitDate(p);//访问当前节点 q = p;//记录这个节点 p = null; }else{//开始遍历右孩子 p = p.right; } } } }
非递归算法的时间复杂度:每个节点都是出栈一次,入栈一次,每个节点访问一次,对于有n个节点的二叉树,设访问每个节点是轻量级的,则上述二叉树的非递归遍历算法的时间复杂度是O(n).
非递归算法的空间复杂度:对于深度为k的二叉树,上述四个算法所需的栈空间与二叉树的深度k成正比,因此空间复杂度是O(k).
- 二叉树遍历的非递归实现(java版)
- Java实现二叉树的递归与非递归遍历
- Java实现二叉树的创建、递归/非递归遍历
- Java实现二叉树的递归、非递归遍历
- 非递归遍历二叉树--java实现
- 二叉树非递归遍历Java实现
- Java实现的二叉树的非递归遍历
- java实现二叉树的非递归遍历
- java中实现二叉树的非递归遍历
- 二叉树的非递归遍历——java实现
- 二叉树遍历的非递归实现 java版本
- 二叉树的非递归遍历---JAVA实现
- java非递归实现二叉树的遍历
- 二叉树的非递归遍历(java实现)
- 二叉树遍历的非递归Java实现
- 非递归实现二叉树的遍历
- 非递归实现二叉树的遍历
- 二叉树遍历的非递归实现
- [JavaMail] 详解Multipart和BodyPart
- #define与enum,你不知道的那些事
- Java8新特性 接口默认方法,接口静态方法
- 【MySQL之设计表(一)】MySQL数据库表设计中的注意事项
- ARM编程模型
- 二叉树遍历的非递归实现(java版)
- (转)分享一个eclipse查看properties文件的地址~
- Spring In Action<一>
- eclipse中修改的文件如何在不重启tomcat(或清缓存)的情况下自动更新到tomcat
- String与StringBuffer的区别
- mysql中的知识点二
- 深入理解 Android 卷I
- ERROR:language "plpgsql" does not exist
- Fractions Again?! UVA