1. 树遍历基础与核心算法解析
树结构在算法竞赛和编程能力认证(如GESP六级)中占据着举足轻重的地位。作为非线性数据结构的典型代表,树的高效遍历是解决复杂问题的关键。本文将深入剖析树的三种基本遍历方式及其衍生应用,帮助读者在GESP六级考试和算法竞赛中游刃有余。
1.1 深度优先遍历(DFS)的实现细节
深度优先遍历如同探险者深入洞穴,选择一条路径走到尽头再回溯。递归实现最为直观:
cpp复制void dfs(TreeNode* node) {
if (!node) return;
// 前序遍历位置
dfs(node->left);
// 中序遍历位置
dfs(node->right);
// 后序遍历位置
}
三种遍历顺序的区别:
- 前序:父节点→左子→右子(适合自顶向下处理)
- 中序:左子→父节点→右子(二叉搜索树有序输出)
- 后序:左子→右子→父节点(适合自底向上处理)
实际应用中,后序遍历往往能简化问题。例如计算子树大小时,必须先知道左右子树的结果才能计算当前节点。
1.2 广度优先遍历(BFS)的层序特性
BFS像水波纹一样逐层扩展,使用队列实现:
cpp复制void bfs(TreeNode* root) {
queue<TreeNode*> q;
q.push(root);
while (!q.empty()) {
TreeNode* cur = q.front(); q.pop();
// 处理当前节点
if (cur->left) q.push(cur->left);
if (cur->right) q.push(cur->right);
}
}
层序遍历的特殊价值:
- 直观展示树的结构层次
- 解决最短路径问题(如树的最小深度)
- 在带权树中计算层累计值
1.3 非递归实现的工程实践
递归虽简洁但存在栈溢出风险,非递归实现更健壮。以前序遍历为例:
cpp复制vector<int> preorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> stk;
while (root || !stk.empty()) {
while (root) {
res.push_back(root->val); // 访问节点
stk.push(root);
root = root->left;
}
root = stk.top()->right;
stk.pop();
}
return res;
}
非递归中序遍历只需调整访问时机,后序遍历则需要记录访问状态。这些实现方式在大规模数据处理时更为可靠。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
