0.为什么要研究二叉树遍历?
A:因为二叉树是非线性结构。
1.二叉树遍历分类:
- 深度优先遍历(前序、中序、后序遍历)
- 广度优先遍历(层序遍历)
2.前序遍历:
输出顺序:根节点 -> 左子树 -> 右子树
代码实现(Java):
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
Deque<TreeNode> stack = new ArrayDeque<>();
while(root != null || !stack.isEmpty()){
//先从根节点往左孩子遍历到底,先读取再压栈
while(root != null){
res.add(root.val);
stack.push(root);
root = root.left;
}
//左孩子到底后逐步弹栈,每一步都检查有无右孩子,有则遍历
TreeNode cur = stack.pop();
root = cur.right;
}
return res;
}
3.中序遍历:
输出顺序: 左子树 -> 根节点 -> 右子树
代码实现(Java):
public List<Integer> inorderTraversal(TreeNode root){
List<Integer> res = new ArrayList<Integer>();
Deque<TreeNode> str = new LinkedList<TreeNode>();
while (root != null || !stk.isEmpty()){
//先向左孩子遍历到底
while (root != null){
stk.push(root);
root = root.left;
}
//左孩子到底再逐步弹出,注意每步检查有无右孩子
root = stk.pop();
res.add(root.val);
root = root.right;
}
return res;
}
4.后序遍历:
输出顺序: 左子树 -> 右子树 -> 根节点
代码实现(Java):
//后序遍历是左右根形式,变形为根右左再反转数组返回
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
Deque<TreeNode> stack = new ArrayDeque<>();
while(root != null || !stack.isEmpty()){
//根到右孩子,遍历到底,先读取在压栈
while(root != null){
res.add(root.val);
stack.push(root);
root = root.right;
}
//到底再逐步弹栈,检查有无左孩子,有则遍历
TreeNode cur = stack.pop();
root = cur.left;
}
//反转数组!!!
Collections.reverse(res);
return res;
}
5.层序遍历:
输出顺序: 根节点 -> 逐层向下(左孩子 -> 右孩子)
代码实现(Java):
public static void levelOrderTraversal(TreeNode root){
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(root);
while (!queue.isEmpty()){
//轮询队列输出第一个数
TreeNode node = queue.poll();
System.out.println(node.data);
//以上一个输出的数为基准检查有无左右孩子,有则入队
if(node.left != null){
queue.offer(node.left);
}
if(node.right != null){
queue.offer(node.right);
}
}
}