非递归遍历的一般手法
利用栈,先不断的找到最左边的节点,然后依次压入栈中,然后栈中元素pop,再向右去找子树,前序遍历和中序遍历比较简单
前序遍历:中左右的顺序,会先在压栈时就将加入list中
中序遍历是在pop后进行加入list
public List<Integer> preorderTraversal(TreeNode root) {
Stack<TreeNode> stack=new Stack<TreeNode>();
List<Integer> list=new ArrayList<Integer>();
while(!stack.empty()||root!=null){
while(root!=null){
list.add(root.val);
stack.push(root);
root=root.left;
}
root=stack.pop();
root=root.right;
}
return list;
}
主要的难点的后序遍历:
首先需要判断当前节点是不是叶子节点(有没有左孩子或右孩子)或其右子树已经被访问过
有疑问看代码注释
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new LinkedList<>();
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
TreeNode last = null;
while(cur != null || !stack.isEmpty()) {
while(cur != null) {
stack.push(cur);
cur = cur.left;
}
cur = stack.peek();//不能pop,需要判断当前节点是不是叶子节点
if (cur.right == null || cur.right == last) { // 右孩子为空或者访问过了,默认左子树为空,不然就跳不///出那个while循环
res.add(cur.val);
stack.pop();
last = cur;//标记为刚被访问的节点
cur = null; //为什么要标记为null,咋说了,一旦满足是叶子节点或右子树已经被访问后,说明这棵子树////已经结束了,需要再从栈里取元素
} else {
cur = cur.right;//如果有右子树没有被访问,需要去将右子树压入栈中
}
}
return res;
}
网友评论