树的遍历

本文主要围绕讲解数据结构中“树”是怎么遍历的,一棵“会讲故事”的二叉树,带你把前序 / 中序 / 后序 / 层序、以及 DFS / BFS 一网打尽。

先立个主角:

    A
   / \
  B   C
 / \   \
D   E   F

把遍历想成“参观一座带分叉走廊的博物馆”。节点是房间,左右子树是左/右走廊。不同遍历,就像不同的参观路线与礼仪顺序。

我们首先看名字前序、中序、后序,怎么定义前中后呢?关键点在于遍历根节点的位置。根节点在前则为前序,以此类推。

前序遍历(Preorder):根 → 左 → 右

参观比喻:到一个房间,先和房主打招呼(访问根),再去左边的房间串门(左子树),最后去右边(右子树)。

顺序:A, B, D, E, C, F

适用场景:

中序遍历(Inorder):左 → 根 → 右(仅二叉树有明确定义)

参观比喻:先把左边所有房间逛完,再回来与房主交谈(根),最后逛右边。

顺序:D, B, E, A, C, F

黄金定律:二叉搜索树(BST)的中序遍历一定是递增有序。 适用场景:

// 中序:左-根-右(BST 中序有序)
void inorderRec(TreeNode* root, vector<int>& out) {
    if (!root) return;
    inorderRec(root->left, out);
    out.push_back(root->val);
    inorderRec(root->right, out);
}

后序遍历(Postorder):左 → 右 → 根

参观比喻:先把孩子们收拾好(左右房间),最后家长收尾(根)。像打扫屋子:先清理各房间,再关门锁屋(根)。

顺序:D, E, B, F, C, A

适用场景:

// 后序:左-右-根(自底向上)
void postorderRec(TreeNode* root, vector<int>& out) {
    if (!root) return;
    postorderRec(root->left, out);
    postorderRec(root->right, out);
    out.push_back(root->val);
}

层序遍历(Level-order):一层一层,从左到右

参观比喻(广场合影):按楼层排队,先一楼再二楼;同层从左到右点名。

顺序:A, B, C, D, E, F

数据结构:队列(queue)——先来先服务。

适用场景:

深度优先(DFS)vs 广度优先(BFS)

DFS(Depth-First Search):一条路走到黑再回头。实现常见有三种“礼仪次序”:前/中/后序。

BFS(Breadth-First Search):按层推进。

一句话:前/中/后序都是 DFS 的不同“拜访时机”;层序就是 BFS。