一次后序遍历即可同时计算叶子数和树高,用结构体(如treestats)封装两个状态,空树返回{0,0},单节点判左右为空则叶子数为1,高度按节点数定义递推;避免重复遍历与空指针错误。

用一次后序遍历同时拿到叶子数和树高
直接递归两次(一次算高度、一次数叶子)效率低,还可能因重复遍历引发栈溢出风险。关键在于把两个状态打包进一次递归返回值——C++ 没有内置二元组返回语法糖,但 std::pair<int int></int> 或自定义结构体足够轻量。
注意:高度定义为「从根到最远叶子的边数」还是「节点数」会影响初始值和递推逻辑。这里统一按「节点数」定义(空树高为 0,单节点树高为 1),叶子节点指左右子树均为 nullptr 的节点。
示例核心逻辑:
struct Result {
int leafCount;
int height;
};
Result dfs(TreeNode* root) {
if (!root) return {0, 0};
auto left = dfs(root->left);
auto right = dfs(root->right);
int h = std::max(left.height, right.height) + 1;
int leaves = (root->left == nullptr && root->right == nullptr) ? 1 : left.leafCount + right.leafCount;
return {leaves, h};
}
空树和单节点树的边界处理必须显式判断
漏掉空指针检查会导致段错误;误判单节点为非叶子会少计数。常见错误是写成 if (!root->left && !root->right) 却没先判 root 是否为空,或者把叶子判定放在递归调用之后却忘了空节点根本不会进入该分支。
- 空树:
root == nullptr→ 返回{0, 0},不能返回{0, -1}或其他魔数 - 单节点:
root != nullptr && root->left == nullptr && root->right == nullptr→ 叶子数贡献为 1 - 非空非叶子节点:叶子数 = 左子树叶子数 + 右子树叶子数,不额外加 1
用 std::pair 还是结构体?看可读性需求
std::pair<int int></int> 写得快,但 first/second 语义模糊,容易写反顺序;结构体字段名明确,调试时也更友好。如果只是临时内部使用且逻辑简单,pair 没问题;若后续要扩展(比如加直径、平衡因子等),结构体更可持续。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
结构体写法示例:
struct TreeStats {
int leafCount = 0;
int height = 0;
};
初始化成员变量能避免未定义值,比裸 struct 更安全。
迭代写法几乎不可行,别硬套栈模拟
想用栈做非递归后序遍历同步统计,需在每个节点出栈时准确知道左右子树的 leafCount 和 height。这意味着要缓存中间结果,实际代码复杂度远超递归,还容易在节点重入、标记位设计上出错。除非有强约束禁止递归(如嵌入式栈空间极小),否则没必要折腾。
真要迭代,优先考虑 BFS 层序遍历+高度计数,但叶子统计仍需额外判断子节点是否存在——本质上还是得扫全树,且无法自然合并两个指标。
递归深度取决于树高,最坏情况(链状树)仍是 O(n) 栈空间,这点无法绕过。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










