如何更快统计左偏树节点数 现有O(N)遍历方案是否可行及如何优化
现有实现问题分析
- 变量作用域错误:代码中使用的
count没有声明作用域,若为全局变量,多次调用traverse函数会出现计数累加错误,必须每次调用前手动重置为0,极易触发bug。 - 计数逻辑冗余重复:你已经在递归中累加左右子树的返回值,又额外执行了
count++操作,会导致最终计数结果偏大,逻辑完全错误。 - 栈溢出风险:当节点数达到数百万级时,递归深度会超过大部分编程语言默认的栈深度上限(通常仅几千到几万),会直接触发栈溢出导致程序崩溃。
修正后可运行的遍历实现
struct Node{ Node* left; Node* right; }; int traverse(Node* node){ if (node == nullptr) return 0; // 基线条件 return 1 + traverse(node->left) + traverse(node->right); }
修正后的版本可以正常返回节点总数,但时间复杂度依然为O(N),仅解决了原有代码的逻辑错误,没有优化大节点规模下的性能问题。如果无法修改左偏树的结构定义,建议将递归遍历改为迭代的广度/深度优先遍历,避免栈溢出问题,稳定性会更好,但时间复杂度不会变化。
最优实现方案
左偏树作为常用的可合并堆实现,所有结构修改操作(插入、合并、删除堆顶)的时间复杂度均为O(logN),你可以通过维护计数元数据的方式,将获取总节点数的时间复杂度降到O(1),具体实现逻辑如下:
- 在左偏树的结构体中新增
size字段,存储当前树的总节点数 - 所有修改左偏树结构的操作执行完成后,同步更新
size值:- 插入单个节点时:
size += 1 - 合并两棵左偏树时:新树的
size = 左树size + 右树size - 删除堆顶节点时:
size = 左子树size + 右子树size
- 插入单个节点时:
- 需要获取总节点数时,直接读取根节点的
size字段即可,无需遍历整棵树
内容的提问来源于stack exchange,提问作者mnijhum
相关产品推荐
相关产品推荐

