关于二叉搜索树(BST)内部路径长度(IPL)计算函数结果不准确的问题咨询
问题分析与修复方案
嘿,你的代码在树层级超过2级时IPL计算出错,咱们来一步步拆解问题,然后给出符合你预期的修复方案:
先明确你的IPL定义
首先看你给出的测试案例:插入10、5、15、30后,正确IPL值为8。这个值对应的是所有节点到根节点的路径上的节点数之和(也就是节点深度之和):
- 根节点10深度为1
- 5和15深度为2
- 30深度为3
总和:1+2+2+3=8
(注:标准的二叉树内部路径长度IPL是所有节点到根的路径边数之和,对应这个案例的话是0+1+1+2=4,但显然你要的是前者的计算结果)
核心问题拆解
1. 全局变量count的滥用
这个全局变量是最大的坑:
- 它不会在每次调用
getIPL前重置,导致多次调用时会在旧值基础上累加错误结果; - 递归处理左右子树时,
count的修改逻辑混乱,比如处理左子树后count已经被修改,处理右子树时会继续叠加,导致深层级节点的贡献被重复计算。
2. getIPL的计算逻辑错误
原函数的递归逻辑完全不符合你需要的深度之和计算:
- 叶子节点直接把
count设为1,忽略了叶子节点的实际深度; - 递归返回的
count是全局累加值,不是当前子树的深度贡献,导致父节点计算时叠加错误数值。
修复后的代码
下面的代码完全去掉全局变量,用递归传递当前节点深度的方式,准确计算所有节点的深度之和:
#include <stdio.h> #include <stdlib.h> typedef struct treeNode { int key; struct treeNode* left; struct treeNode* right; } treeNode; treeNode* insertNode(treeNode** t1, int x) { if (*t1 == NULL) { *t1 = malloc(sizeof(treeNode)); (*t1)->key = x; (*t1)->left = NULL; (*t1)->right = NULL; } else if (x < (*t1)->key) { // 插入左子树 (*t1)->left = insertNode(&(*t1)->left, x); } else if (x > (*t1)->key) { // 插入右子树 (*t1)->right = insertNode(&(*t1)->right, x); } else { printf("SameValue exist.\n"); } return *t1; } // 辅助递归函数:传递当前节点的深度,累加所有节点的深度之和 int calculateDepthSum(treeNode* node, int currentDepth) { if (node == NULL) { return 0; } // 当前节点深度 + 左子树所有节点深度之和 + 右子树所有节点深度之和 return currentDepth + calculateDepthSum(node->left, currentDepth + 1) + calculateDepthSum(node->right, currentDepth + 1); } // 对外调用的IPL计算函数,根节点初始深度为1 int getIPL(treeNode* root) { return calculateDepthSum(root, 1); } int main() { treeNode* T1 = NULL; // 测试案例1:10、5、15 insertNode(&T1, 10); insertNode(&T1, 5); insertNode(&T1, 15); printf("IPL (10,5,15): %d\n", getIPL(T1)); // 输出5,符合预期 // 插入30后测试 insertNode(&T1, 30); printf("IPL (add 30): %d\n", getIPL(T1)); // 输出8,符合你的正确值 return 0; }
代码说明
- 去掉了全局变量
count,改用递归时传递当前节点的深度,避免了全局状态的干扰; - 递归逻辑清晰:每个节点的贡献是自身深度,加上左右子树所有节点的深度之和;
- 完全符合你给出的测试案例预期:插入10、5、15后输出5,插入30后输出8。
内容的提问来源于stack exchange,提问作者Hyeonbinshin




