這裏簡要介紹一下樹的迭代方式遍歷
前序遍歷 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;
}
}