以前一直认为递归遍历二叉树是天经地义,今天遇到了要求使用非递归来遍历二叉树,决定思考一下这个问题
前序遍历
用栈来实现:
1.开始先将头结点加入栈中
2.弹出栈。输出弹出元素
3.将节点右元素入栈
4.将节点左元素入栈
重复 2–4知道栈空
为什么要先压入右元素呢?因为我们要确保先访问到的是左节点
前序遍历代码:
public ArrayList<Integer> preorderTraversal(TreeNode root) {
ArrayList<Integer> list = new ArrayList<>();
if(root == null) return list;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while(!stack.isEmpty()){
TreeNode now = stack.pop();
list.add(now.val);
if(now.right != null) stack.push(now.right);
if(now.left != null) stack.push(now.left);
}
return list;
}
后序遍历
和前序遍历很类似
用栈来实现:
1.开始先将头结点加入栈中
2.弹出栈。将节点的值加入列表的头结点(也可以直接加入一个队列)
3.将节点左元素入栈
4.将节点右元素入栈
重复 2–4直到栈空
简单的说就是将序列倒序输出
public ArrayList<Integer> postorderTraversal(TreeNode root) {
ArrayList<Integer> list = new ArrayList<>();
if(root == null) return list;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while(!stack.isEmpty()){
TreeNode now = stack.pop();
list.add(0,now.val);
if(now.left != null) stack.push(now.left);
if(now.right != null) stack.push(now.right);
}
return list;
}
另一种更常规的后续非递归遍历写法
public ArrayList<Integer> postorderTraversal2(TreeNode root) {
ArrayList<Integer> list = new ArrayList<>();
if(root == null) return list;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
TreeNode pre = null;
while(!stack.isEmpty()){
TreeNode now = stack.peek();
if((now.left == null && now.right == null) || (pre != null && (now.left == pre || now.right == pre))){
list.add(now.val);
stack.pop();
pre = now;
}
else{
if(now.right!=null) stack.push(now.right);
if(now.left !=null) stack.push(now.left);
}
}
return list;
}
中序遍历
对于任一结点p:
step 1:若其左孩子不为空,则将p入栈,并将p的左孩子置为当前的p。然后对当前结点p再进行相同的处理。
step 2:若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将栈顶结点的右孩子置为当前的P结点。
step 3:直到p为NULL并且栈为空则遍历结束。
public ArrayList<Integer> inorderTraversal2(TreeNode root){
ArrayList<Integer> list = new ArrayList<>();
if(root == null) return list;
Stack<TreeNode> stack = new Stack<>();
TreeNode p = root;
while (!stack.isEmpty() || p != null) {
while(p != null){
stack.push(p);
p = p.left;
}
if(!stack.isEmpty()){
p = stack.pop();
list.add(p.val);
p = p.right;
}
}
return list;
}