这里简要介绍一下树的迭代方式遍历
前序遍历 leetcode 94
使用栈来模拟递归,出栈时候访问结点。前序遍历先访问左子树,再访问右子树,那么入栈时相反,即先入右子树,再入左子树。那么出栈的时候就是前序遍历的顺序。
class PreOrder {
ArrayList<Integer> result = new ArrayList<>();
public ArrayList<Integer> preorderTraversal(TreeNode root) {
if ( root!=null ) {
TreeNode cur = null;
Stack<TreeNode> s = new Stack<>();
s.push(root);
while ( !s.isEmpty() ) {
cur = s.pop();
result.add(cur.val);
if( cur.right!=null ) {
s.push(cur.right);
}
if ( cur.left!=null ) {
s.push(cur.left);
}
}
}
return result;
}
}
后序遍历 LeetCode 145
后序遍历是 左 右 中。同前序遍历一样,也是在出栈的时候访问数据。我们先将所有左子树的左结点加入到栈中,每pop出一个结点,意味这个结点的左子树已经被访问完毕。所以我们只考虑右子树的情况。
当右子树为空,那么此结点可以访问。
当右子树非空,1) 右子树已被访问,直接输出该结点
2)右子树没被访问,访问右子树。
如何确定右子树是否被访问,就需要一个last结点来记录。
class Postorder {
ArrayList<Integer> result = new ArrayList<>();
public ArrayList<Integer> postorderTraversal(TreeNode root) {
TreeNode cur = root;
TreeNode last = null;
Stack<TreeNode> s = new Stack<>();
while ( cur!=null ) {
s.push(cur);
cur = cur.left;
}
while ( !s.isEmpty() ) {
cur = s.pop();
if ( cur.right!=null && last!=cur.right ) {
s.push(cur);
cur = cur.right;
while ( cur!=null ) {
s.push(cur);
cur = cur.left;
}
} else {
result.add(cur.val);
last = cur;
}
}
return result;
}
}
中序遍历 LeetCode 144
同前序遍历,注意入栈顺序即可。
class Inorder {
ArrayList<Integer> result = new ArrayList<>();
Stack<TreeNode> s = new Stack<>();
public ArrayList<Integer> inorderTraversal(TreeNode root) {
TreeNode cur = root;
while ( cur!=null || !s.isEmpty() ) {
if ( cur!=null ) {
s.push(cur);
cur = cur.left;
} else {
cur = s.pop();
result.add(cur.val);
cur = cur.right;
}
}
return result;
}
}