统计叶子节点数需严格判断左右子树均为空,空指针返回0;树高按空树为-1定义,递归公式为1+max(左高,右高);可一次遍历用pair同时返回叶子数和高度,避免重复DFS。

统计叶子节点数量:递归终止条件必须严格判断
叶子节点的定义是左右子树都为空的节点,不是“没有子节点”这种模糊描述。很多初学者会误判 nullptr 节点本身为叶子,或漏掉某侧为空另一侧非空时的排除逻辑。
- 递归函数返回值应为
int,遇到空指针直接返回0 - 只有当
node->left == nullptr && node->right == nullptr才计数1 - 否则递归累加左右子树结果,不额外加
1
int countLeaves(TreeNode* root) {
if (!root) return 0;
if (!root->left && !root->right) return 1;
return countLeaves(root->left) + countLeaves(root->right);
}
注意:如果用 root == nullptr 判断,和 !root 效果一致,但后者更常见;若结构体字段名是 left/right,别写成 lchild 或 lc 导致编译失败。
计算树的高度:空树高度定义为 -1 还是 0?
C++ 中没有标准约定,但工程中普遍采用“空树高度为 -1”,这样叶子节点高度为 0,与多数教材和算法题(如 LeetCode)一致。若按“空树为 0”,则叶子节点高度为 1,容易在平衡判断(如 AVL)中出错。
- 高度定义是最长路径上的边数(或节点数减 1),不是节点个数
- 递归公式:
height = 1 + max(height(left), height(right)) - 基础情形:
if (!root) return -1;
int getHeight(TreeNode* root) {
if (!root) return -1;
return 1 + std::max(getHeight(root->left), getHeight(root->right));
}
别用 abs 或 min 替代 max;std::max 需要 #include <algorithm>,否则编译报错 error: 'max' was not declared in this scope。
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
一次遍历同时完成两个任务:避免重复递归开销
叶子数和高度本质都需要遍历整棵树,分开调用会触发两轮 DFS,时间复杂度从 O(n) 变成 O(2n)。对大树或高频调用场景(如实时渲染中的场景图),这点开销不可忽略。
- 定义一个结构体或 pair 返回两个值,例如
std::pair<int, int>(叶子数, 高度) - 递归中分别获取左右子树的
pair,再合并计算 - 空节点统一返回
{0, -1}
std::pair<int, int> getLeavesAndHeight(TreeNode* root) {
if (!root) return {0, -1};
auto [l_leaves, l_h] = getLeavesAndHeight(root->left);
auto [r_leaves, r_h] = getLeavesAndHeight(root->right);
int leaves = (l_leaves + r_leaves) + (l_h == -1 && r_h == -1 ? 1 : 0);
int height = 1 + std::max(l_h, r_h);
return {leaves, height};
}
注意 C++17 结构化绑定语法要求编译器支持 -std=c++17;若用旧标准,改用 .first/.second 访问。
边界情况验证:单节点、空树、倾斜树必须覆盖
实际使用中,最容易出问题的是极端结构:
- 空树:
root == nullptr→ 叶子数应为0,高度为-1 - 单节点:
root存在且左右为空 → 叶子数1,高度0 - 左斜树(只有 left):叶子数始终为
1,高度等于节点总数减 1
测试时别只用教科书示例图;建议手写三行测试:
TreeNode* t1 = nullptr; // 空 TreeNode* t2 = new TreeNode(1); // 单节点 TreeNode* t3 = new TreeNode(1); t3->left = new TreeNode(2); t3->left->left = new TreeNode(3); // 左斜
最后提醒:所有递归实现都依赖栈空间,深度超过系统默认栈限制(Linux 一般 8MB)会触发 segmentation fault。超深树请改用迭代 DFS 或 BFS,但叶子统计和高度计算的迭代写法远不如递归直观,容易引入额外 bug。

















