二叉树的中序遍历
题目描述
题目分析
先序遍历的场景,例如图中的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;
}
}
}