3、二叉树:先序,中序,后序循环遍历详解

原创博客,转载请注明出处,谢谢~~~



  

设计二叉树的循环遍历算法对于深刻理解二叉树很有帮助。下面就详细分析3个循环遍历算法。

1、先序循环遍历算法

在自己设计循环遍历算法的时候,感觉先序遍历算法设计最为容易。下面把设计思路写下来,以防遗忘。

先序循环遍历二叉树的思路最为直接,规则就是

①. 从根结点开始沿着左孩子一直走到头,在此过程中,每到达一个结点便访问其元素值(如,输出),同时检测该结点是否有右孩子,如果有则将指向右孩子的引用入栈;

②. 第一步完成以后,弹出一个栈顶引用作为本次循环的根节点,并重复步骤①,直到栈为空;

例如上图:

1. 从根节点A开始,输出A的元素值。同时,A有右孩子F,所以将A.rchild入栈,即:stack.push(A.rchild)。

2. 沿A左孩子走到B,输出B的元素值,同时B有右孩子D,所以将B.rchild入栈。

3. 沿B的左孩子走到C,输出C的元素值,C没有右孩子了,说明此次以A作为根节点的循环结束。

4. 接着检测堆栈。如果堆栈不为空,弹出一个值作为根节点重复1~4步骤;如果堆栈为空,则遍历结束。

再从图上面形象的理解遍历过程:总是从右上到左下依次进行。如图中标注为“1”、“2”、“3”、“4”的红色线条。

依据上面的理解,不难写出先序循环遍历的代码:

 1 /**
 2      * 先序循环遍历法。
 3      * @return true 表示完全遍历;<br>false 表示满足条件终止遍历;
 4      */
 5 public boolean preOrderCircleTraverse(){
 6     if(root == null)
 7         return true;
 8
 9     Stack<Node> stack = new Stack<>();
10     stack.push(root);
11     Node nod = null;
12
13     while(!stack.empty()){//开始下一次从右上到左下的循环
14         nod = stack.pop();
15         while(nod != null){
16             if(!visitElem(nod))//访问结点的元素
17                 return false;
18             if(nod.getRchild() != null)//有右孩子,就入栈
19                 stack.push(nod.getRchild());
20             nod = nod.getLchild();
21         }
22     }
23     return true;
24 }        

2、中序循环遍历算法。

时间: 2024-10-31 00:57:50

3、二叉树:先序,中序,后序循环遍历详解的相关文章

分别求二叉树前、中、后序的第k个节点

一.求二叉树的前序遍历中的第k个节点 //求先序遍历中的第k个节点的值 int n=1; elemType preNode(BTNode *root,int k){ if(root==NULL) return ' '; if(n==k) return root->data; n++; elemType ch = preNode(root->lchild,k); if(ch!=' ') return ch; ch = preNode(root->rchild,k); return ch;

算法进化历程之“根据二叉树的先序和中序序列输出后序序列”

巧若拙(欢迎转载,但请注明出处:http://blog.csdn.net/qiaoruozhuo) 前不久在看到一个作业"根据二叉树的先序和中序序列输出后序序列",当时我参考<数据结构与算法(C语言)习题集>上的做法,先根据先中序序列确定一颗二叉树,然后后序遍历二叉树输出后序序列. 函数采用了递归算法,利用函数传入的先序和中序序列的左右边界,确定要处理的序列段,生成相应的二叉树. 基本思路是,把该段先序序列的第一个元素作为当前二叉树的根结点,然后在中序序列找到根结点.根结点

通过二叉树的中序序列和后序序列获取前序序列

二叉树的遍历方式常见的三种是:先序遍历(ABC).中序遍历(BAC).后序遍历(BCA) 先序遍历: 若二叉树为空,则空操作:否则: 访问根结点; 先序遍历左子树: 先序遍历右子树. 中序遍历: 若二叉树为空,则空操作:否则: 中序遍历左子树: 访问根结点: 中序遍历右子树. 后序遍历: 若二叉树为空,则空操作:否则: 后序遍历左子树: 后序遍历右子树: 访问根结点. 在学习到 根据遍历序列确定二叉树 时,知道了:可以通过二叉树的先中或者中后遍历序列唯一确定一棵二叉树. 根据算法描述 使用jav

二叉树——前序遍历、中序遍历、后序遍历、层序遍历详解(递归非递归)

前言 前面介绍了二叉排序树的构造和基本方法的实现.但是排序遍历也是比较重要的一环.所以笔者将前中后序.和层序遍历梳理一遍. 了解树的遍历,需要具有的只是储备有队列,递归,和栈.这里笔者都有进行过详细介绍,可以关注笔者数据结构与算法专栏.持续分享,共同学习. 层序遍历 层序遍历.听名字也知道是按层遍历.我们知道一个节点有左右节点.而每一层一层的遍历都和左右节点有着很大的关系.也就是我们选用的数据结构不能一股脑的往一个方向钻,而左右应该均衡考虑.这样我们就选用队列来实现. 对于队列,现进先出.从根节

先序序列和后序序列并不能唯一确定二叉树

数据结构的基础知识中重要的一点就是能否根据两种不同遍历序列的组合(有三种:先序+中序,先序+后序,中序+后序),唯一的确定一棵二叉树.然后就是根据二叉树的不同遍历序列(先序.中序.后序),重构二叉树.显然,这三种组合并不是都能唯一确定二叉树的,其中先序+后序就不能唯一确定一棵二叉树,其他两种组合可以唯一的确定一颗二叉树. 由先序序列和后序序列不能唯一确定一棵二叉树,因无法确定左右子树两部分. 反例:任何结点只有左子树的二叉树和任何结点只有右子树的二叉树,其前序序列相同,后序序列相同,但却是两棵不

中序表达式转后序表式式

中序表达式转后序表式式: 将中序表达式所有括号补全,然后将所有运算符向右移出无匹配的第一个右括号,去掉括号即为后序表式式 举例: 原式:a+b*(c+d/e) 补全括号:(a+(b*(c+(d/e)))) 操作符右移:(a(b(c(de)/)+)*)+ 去掉括号:abcde/+*+ 中序表达式转前序表式式: 将中序表达式所有括号补全,然后将所有运算符向左移出无匹配的第一个左括号,去掉括号即为前序表式式 举例: 原式:a+b*(c+d/e) 补全括号:(a+(b*(c+(d/e)))) 操作符右移

PHP中的命名空间(namespace)及其使用详解

PHP中的命名空间(namespace)及其使用详解 晶晶 2年前 (2014-01-02) 8495次浏览 PHP php自5.3.0开始,引入了一个namespace关键字以及__NAMESPACE__魔术常量(当然use关键字或use as嵌套语句也同时引入):那么什么是命名空间呢?php官网已很明确的进行了定义并形象化解释,这里直接从php官网copy一段文字[来源]. “什么是命名空间?从广义上来说,命名空间是一种封装事物的方法.在很多地方都可以见到这种抽象概念.例如,在操作系统中目录

struts2.0中Action的对象生命周期详解!!(转)

原文出处:http://blog.csdn.net/wxy_g/article/details/2071662 有很多人问Struts2.0中的对象既然都是线程安全的,都不是单例模式,那么它究竟何时创建,何时销毁呢? 这个和struts2.0中的配置有关,我们来看struts.properties ### if specified, the default object factory can be overridden here ### Note: short-hand notation is

Angular.js中处理页面闪烁的方法详解

Angular.js中处理页面闪烁的方法详解 前言 大家在使用{{}}绑定数据的时候,页面加载会出现满屏尽是{{xxx}}的情况.数据还没响应,但页面已经渲染了.这是因为浏览器和angularjs渲染页面都需要消耗一定的时间,这个间隔可能很小,甚至让人感觉不到,这种情况一切正常,但这个时间也可能很长,这时候用户可能会看到满屏尽是{{xxxx}}.这种情况被叫做"Flash Of Unrendered Content (FOUC)(K)?and is always unwanted.".