赞
踩
真没想到一个非递归中序遍历也能搞死我。我是有多弱啊,更别说后续遍历了。
看看人家的代码,那真是八仙过海,各显神通,弱爆了就是我啊就是我
方法1: 参考http://blog.csdn.net/wzy_1988/article/details/17072953
- ArrayList<Integer> s1(TreeNode root){
- ArrayList<Integer> list=new ArrayList<Integer>();
- Stack<TreeNode> st=new Stack<TreeNode>();
- TreeNode pre=null;
- while(st.size()>0||root!=null){
- if(root!=null){
- st.push(root);
- root=root.left;
- }else{
- root=st.pop();
- if(root.right==null||root.right==pre){
- list.add(root.val);
- pre=root;
- root=null;
- }else{
- st.push(root);
- root=root.right;
- }
- }
- }
- return list;
- }
先看一下大神1的方法,和中序前序遍历一样,首先遍历最左子树,这个没问题,一直走while里的if模块。
一直走到左子树没有了,这时候pop一下取出来最后一个点。这时候,
如果是中序遍历就可以直接加上这个点然后走右边了,
如果是先序遍历更简单,在if里就add到list里就行,这里也是直接走右孩子就可以。
但是这是后序遍历,后序遍历里中间节点最后查看,所以这里要判断一下,如果没有右孩子或者右边孩子已经遍历过(pre来存上次遍历的点),那么就可以加入这个点了。也就是两个else中间的代码,注意这里有一句root=null值得分析一下。其实这里还有一个隐式约定:root==null既是循环增加左子树完毕的判定条件,也是后面遍历过程中要求pop新节点的请求条件。
然后就简单了,如果不能加入这个点,对不起还得把你塞回去,然后下一次遍历root.right就ok。
如果顺着先序和中序写下来多半想到的是这种方法。
方法2: 参考http://www.cnblogs.com/TenosDoIt/p/3416835.html
- ArrayList<Integer> s2(TreeNode root){
- ArrayList<Integer> list=new ArrayList<Integer>();
- Stack<TreeNode> st=new Stack<TreeNode>();
- if(root==null)
- return list;
- st.push(root);
- TreeNode pre=null;
- while(st.size()>0){
- root=st.peek();
- if((root.left==null&&root.right==null)||(pre!=null&&(pre==root.left||pre==root.right))){
- list.add(root.val);
- pre=root;
- st.pop();
- }else{
- if(root.right!=null)
- st.push(root.right);
- if(root.left!=null)
- st.push(root.left);
- }
- }
- return list;
- }
再看看大神2的方法,这两种方法复杂度肯定是完全一致的,但思路却完全不同。
连循环加入左节点的步骤都省下了,真是太猛了。
第一步,root入栈。
第二步,peek一个节点。然后分两种情况判断:
情况1: 如果是叶节点,或者刚处理了它的左节点或者右节点(注意!这里一定要加上左节点,不然必错,想想为啥?),那么就在list上假如这个结果,pop了这个节点,pre记录下处理了这个节点。
情况2: 非情况1的情况,即这点或者不是叶节点,且,这个点的左右子节点都没有处理,那么处理这个点。处理方式:st.push(root.right); st.push(root.left);
咱们走一遍整个逻辑,假设树={1,2,3,4,5,6,7}先走根节点,不是叶节点且子节点都没处理,所以加入3,2。循环走完第一遍,peek=2,假如5,4,循环第二遍走完。
第三遍: peek=4,叶节点,加入4为第一个值,pre=4;
第四遍:peek=5 加入结果 4,5 pre=5
5: peek=2,pre=5,为右孩子,4,5,2
6:peek=3, add 7,6, stack=1,3,7,6 pre=5
peek 6 peek 7 peek 3 peek 1 结束。
怎么看怎么那个pre=root.left判不到对吧,再来个树1,2,3,4,#,#,#, 再走一遍就明白了,走4之后,没有右孩子,所以走2,你没有pre=root.left 不是找死么
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。