二叉树的非递归遍历方式(Java)
前序遍历
思路:就是通过一个栈来实现:
-
从root开始,root非空先入栈;
-
进入循环判断,若栈非空,则弹出栈顶元素,打印栈顶元素的值
-
当弹出的栈顶元素的右子节点非空时,将右子节点压入栈;
-
当弹出的栈顶元素的左子节点非空时,将左子节点压入栈;
-
直到栈中无元素。
代码:
public static ArrayList<Integer> preOrder(TreeNode root){ ArrayList<Integer> list =new ArrayList<>(); ArrayDeque<TreeNode> stack=new ArrayDeque<>(); if(root!=null){ stack.push(root); while(!stack.isEmpty()){ root=stack.pop(); list.add(root.val); if(root.right!=null){ stack.push(root.right); } if(root.left!=null){ stack.push(root.left); } } } return list; }
中序遍历
思路:也是通过一个栈来实现
中序遍历需要一直遍历到最左的子节点,所以
-
若左子节点非空,则将此节点压入栈中,执行root=root.left;
-
直到左子节点为空,此时弹出栈顶元素,并打印出该栈顶节点的值,并将其右子节点加入栈中;
-
循环直至栈中为空。
public static ArrayList<Integer> inorder(TreeNode root){ ArrayList<Integer> list=new ArrayList<>(); ArrayDeque<TreeNode> stack=new ArrayDeque<>(); if(root!=null){ while(root!=null || !stack.isEmpty()){ if(root!=null){ stack.push(root); root=root.left; }else{ root=stack.pop(); list.add(root.val); root=root.right; } } } return list; }
后序遍历
思路:后续遍历需要两个栈进行,因为当前节点要最后打印,所以一个栈复制正常入栈,另一个栈则压入第一个栈弹出的元素,这样就保证了后序性质。
public ArrayList<Integer> afterOrder(TreeNode root){
ArrayList<Integer> list=new ArrayList<>();
ArrayDeque<TreeNode> stack1=new ArrayDeque<>();
ArrayDeque<TreeNode> stack2=new ArrayDeque<>();
if (root!=null) {
stack1.push(root);
while(!stack1.isEmpty()) {
root = stack1.pop();
stack2.push(root);
if (root.left != null) {
stack1.push(root.left);
}
if (root.right != null) {
stack1.push(root.right);
}
}
while (!stack2.isEmpty()) {
list.add(stack2.pop().val);
}
}
return list;
}