二叉樹的中序遍歷
題目描述
題目分析
先序遍歷的場景,例如圖中的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;
}
}
}