Leetcode No.94 二叉樹的中序遍歷(循環法,含先序、中序、後序通用解解題技巧)

二叉樹的中序遍歷

題目描述

在這裏插入圖片描述

題目分析

先序遍歷的場景,例如圖中的ABCDE,正常的先序遍歷順序應該是從A出發,先打印A 然後從A訪問到B再打印B,再從B訪問到D再打印D,再從B訪問到E打印E,在訪問到F打印F,最後打印C。即被打印的左節或右節點點爲葉子節點時,就去打印右節點。最終的結果是A,B,D,E,F,C。
這個時候,我們可以準備一個堆棧,將根元素(A)入棧並彈出後打印,此時A有BC兩個左右子節點,先入C再入B,然後彈出並打印B,此時B有D和E兩個子節點,此時將E和D依次入棧,再打印D,再打印E,此時E有一個左子節點,將F入棧,然後彈出F,再彈出最後的元素C,最終遍歷出整個二叉樹。
在這裏插入圖片描述
再來看一下中序遍歷,它的特點是必須將A左邊的節點全部遍歷完才能遍歷右邊。遍歷順序爲 先訪問A(此時不打印),再訪問B~D,D爲葉子節點,打印D,再打印B ,再訪問E(非葉子),再打印F,再打印E,在打印A,最終打印C。結果爲D,B,F,E,A,C。
這個時候我們就發現了一個規律,在遍歷樹時,都是先訪問某個節點,然後在根據它的遍歷順序去打印這個節點。比如先序遍歷中,我們先打印了A,然後訪問了B和C。這個時候我們再站在B的角度來看,打印了B後訪問了D和E,以此類推,最終遍歷整個樹。這個時候我們發現它可以被拆解成一個子操作。即打印A並訪問B和C的動作可以應用到其子節點中。
我們可以定義一個操作類,將節點訪問順序記錄下來,然後依次打印。

  class IterInfo {
        int verb; //操作符 0代表訪問 1代表打印
        TreeNode node; //當前被記錄的節點
        public IterInfo(int verb, TreeNode node) {
            this.verb = verb;
            this.node = node;
        }
    }

實現代碼

前序遍歷

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    
    public List<Integer> preorderTraversal(TreeNode root) {
    List<Integer> result = new ArrayList<>();
    Deque<IterInfo> queue = new ArrayDeque<>();
    queue.add(new IterInfo(0, root));
    while(!queue.isEmpty()){
        IterInfo info = queue.removeFirst();
        if(info.node == null) continue;
        if(info.verb == 1) {
            result.add(info.node.val);
        } else { 
            queue.addFirst(new IterInfo(0, info.node.right));
            queue.addFirst(new IterInfo(0, info.node.left));
            queue.addFirst(new IterInfo(1, info.node));
        }
    }
    return result;
    }
    
    
    class IterInfo {
        int verb; //操作符 0代表訪問 1代表打印
        TreeNode node;
        public IterInfo(int verb, TreeNode node) {
            this.verb = verb;
            this.node = node;
        }
    }
  
    
}

中序遍歷【只需要改變入棧順序即可】

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        Deque<IterInfo> queue = new ArrayDeque<>();
        queue.add(new IterInfo(0, root));
        while(!queue.isEmpty()){
            IterInfo info = queue.removeFirst();
            if(info.node == null) continue;
            if(info.verb == 1) {
                result.add(info.node.val);
            } else { 
                queue.addFirst(new IterInfo(0, info.node.right));
                queue.addFirst(new IterInfo(1, info.node));
                queue.addFirst(new IterInfo(0, info.node.left));
                
                
            }
        }
        return result;
    }
    
    
    class IterInfo {
        int verb; //操作符 0代表訪問 1代表打印
        TreeNode node;
        public IterInfo(int verb, TreeNode node) {
            this.verb = verb;
            this.node = node;
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章