真没想到一个非递归中序遍历也能搞死我。我是有多弱啊,更别说后续遍历了。
看看人家的代码,那真是八仙过海,各显神通,弱爆了就是我啊就是我
方法1: 参考http://blog.youkuaiyun.com/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 不是找死么