二叉树的非递归遍历
2016-02-27 21:25
246 查看
先写下这个问题的模式
首先我们要把非空的root节点入栈,在循环里不断的推断出栈,然后处理栈顶元素及左孩子结点和右孩子结点。
我们先看下当前的栈顶元素怎么处理。先根遍历的顺序是:【根 左 右】。而我们每次处理的栈顶元素的身份事实上都恰好是根。所以我们就能够直接把这个根几点输出或放入结果容器中;那么其左孩子和右孩子怎样处理呢?既然是模拟递归,那么肯定要入栈进行保存的,谁先入栈呢?考虑到栈的性质,我们应该让其右孩子先入栈,左孩子后入栈,这样,栈顶就是左孩子,下次先出栈的就是左孩子。这样就符合先根遍历的顺序了。
再回过头来看下在左右孩子没入栈之前。我们不过获得了栈顶元素。该元素还依旧在栈中,那么它在栈中还有意义吗?非常明显没有意义了,由于它的信息我们已经输出,而其左右孩子在入栈后就再也不须要它了,所以就应该在左右孩子入栈前将其pop掉。
相同。后根遍历也是如此。尽管后根的遍历是【左 右 根】,可是我们毕竟是知道根要放在哪里。差别就是子节点的入栈顺序的变化。
麻烦点的应该是中根遍历【左 根 右】。如前所述,我们处理的当前栈顶节点是视为根结点的,可是这个根结点却不知该放在结果中的哪里,放在前面,前面应该是左的位置。放在右面,右边应该是右孩子的位置,放中间?哪里算中间?1-10, 2 是中间还是3是中间?我们不确定。由于左右孩子的个数我们无从得知。
看来此时的栈顶元素不能像先根和后根那样。直接输出,还得在栈里面挤一下才好,不然总不能直接丢弃。
之所以当前的栈顶根不能输出,是由于它的左还没有确定,那么我们仅仅要把它的左都输出了。就能够确定当前根的位置了。
def preorderTraversal(self, root): if root == None: return [] re = [] insert root to stack s while s not empty: cur_root = top of stack s s.pop() how to handle cur_root how to handle cur_root.left how to handle cur_root.right
首先我们要把非空的root节点入栈,在循环里不断的推断出栈,然后处理栈顶元素及左孩子结点和右孩子结点。
我们先看下当前的栈顶元素怎么处理。先根遍历的顺序是:【根 左 右】。而我们每次处理的栈顶元素的身份事实上都恰好是根。所以我们就能够直接把这个根几点输出或放入结果容器中;那么其左孩子和右孩子怎样处理呢?既然是模拟递归,那么肯定要入栈进行保存的,谁先入栈呢?考虑到栈的性质,我们应该让其右孩子先入栈,左孩子后入栈,这样,栈顶就是左孩子,下次先出栈的就是左孩子。这样就符合先根遍历的顺序了。
再回过头来看下在左右孩子没入栈之前。我们不过获得了栈顶元素。该元素还依旧在栈中,那么它在栈中还有意义吗?非常明显没有意义了,由于它的信息我们已经输出,而其左右孩子在入栈后就再也不须要它了,所以就应该在左右孩子入栈前将其pop掉。
def preorderIter(self, root): if None == root: return [] re = []; s = [] s.append(root) while len(s): cur_root = s.pop() print cur_root.val re.append(cur_root.val) if cur_root.right: s.append(cur_root.right) if cur_root.left: s.append(cur_root.left) return re
相同。后根遍历也是如此。尽管后根的遍历是【左 右 根】,可是我们毕竟是知道根要放在哪里。差别就是子节点的入栈顺序的变化。
def postorderIter(self, root): if None == root: return re = [] # store results s = [] # node stack s.append(root) while len(s): cur_root = s.pop() re.insert(0,cur_root.val) if cur_root.left: s.append(cur_root.left) if cur_root.right: s.append(cur_root.right) return re
麻烦点的应该是中根遍历【左 根 右】。如前所述,我们处理的当前栈顶节点是视为根结点的,可是这个根结点却不知该放在结果中的哪里,放在前面,前面应该是左的位置。放在右面,右边应该是右孩子的位置,放中间?哪里算中间?1-10, 2 是中间还是3是中间?我们不确定。由于左右孩子的个数我们无从得知。
看来此时的栈顶元素不能像先根和后根那样。直接输出,还得在栈里面挤一下才好,不然总不能直接丢弃。
之所以当前的栈顶根不能输出,是由于它的左还没有确定,那么我们仅仅要把它的左都输出了。就能够确定当前根的位置了。
def inorderIter(self, root): if None == root: return [] re = [] s = [] s.append(root) while len(s): cur_root = s[-1] # push, until the last letf while cur_root.left: s.append(cur_root.left) cur_root = cur_root.left # pop, until one node has right while len(s): cur_root = s[-1] print cur_root.val re.append(cur_root.val) s.pop() if cur_root.right: s.append(cur_root.right) break return re
相关文章推荐
- uva 437 The Tower of Babylon
- 1.什么是泛型和C#中泛型在Class上的实现
- Java类和封装学习心得(1)
- 1072. Gas Station (30)
- mapreduce编程(一)-二次排序
- iOS通讯录开发
- 1034. 有理数四则运算(20)
- java学习——入门扫盲篇
- python环境准备
- VS中包含目录、附加依赖项、附加库目录,启动项目的设置及具体设置
- Python图像处理库PIL的ImageFile模块介绍
- 图片压缩后长度和宽度 及像素坐标
- Diffuse_shadow顶点着色点光源阴影实现
- 如何分析业务问题
- JAVA 读取properties配置文件 - 全局搜索路径
- 关于移动互联网产品的指标分析初探
- Validate Binary Search Tree
- php+ajax实现登录验证
- java调用COM组件的几种工具
- C语言和设计模式(继承、封装、多态)