板子:带深度参数的递归——WPL(2014)
WPL 是所有叶子的「权值
路径长度」之和。深度作为参数往下传(前序的思路),走到叶子就把「权值 深度」交上来。
代码
int wplDfs(BiTree T, int depth) { // depth:T 到根的路径长度(边数),根为 0
if (T == NULL) return 0;
if (T->lchild == NULL && T->rchild == NULL)
return T->data * depth; // 叶子:权值 × 路径长度
return wplDfs(T->lchild, depth + 1) + wplDfs(T->rchild, depth + 1); // 孩子比自己深一层
}
int WPL(BiTree root) {
return wplDfs(root, 0); // 根的路径长度是 0
}
int WPL2(BiTree root) { // 另一种解法:层序遍历,按层处理
BiTNode *q[MaxSize];
int front = 0, rear = 0, depth = 0, wpl = 0;
if (root != NULL) q[rear++] = root;
while (front < rear) {
int cnt = rear - front; // 当前这一层的结点数
while (cnt-- > 0) {
BiTNode *p = q[front++];
if (p->lchild == NULL && p->rchild == NULL) wpl += p->data * depth; // 叶子才累加
if (p->lchild != NULL) q[rear++] = p->lchild;
if (p->rchild != NULL) q[rear++] = p->rchild;
}
depth++; // 这一层处理完,深度 +1
}
return wpl;
}复杂度:两种解法都是时间
例:根有两个孩子,左孩子下面挂着权值为 2、3 的两个叶子,右孩子是权值为 5 的叶子。WPL
考场答案要点(2014)
- 原题的结点字段是
left | weight | right。考场上把data换成weight、把lchild/rchild换成left/right。 - (1)设计思想:先序遍历二叉树,用参数
depth记录当前结点的深度(根为 0)。遇到叶子,就把「权值深度」累加到结果中;非叶结点把 depth + 1传给左右孩子。 - (3)复杂度:每个结点访问一次,时间
;递归栈深度为树高,空间 。
关键边界
- 路径长度是边数:根的路径长度是 0,所以要从
wplDfs(root, 0)开始。如果习惯让根在第 1 层,叶子就要乘depth - 1。 - 只累加叶子。原题中只有叶子的
weight有意义,非叶结点的权值不算。
易错点
- 也可以用全局变量或
static变量累加。这种写法没问题,但多次调用前要记得清零。 - 手算哈夫曼树时有个捷径:WPL 等于所有非叶结点的权值之和(每个非叶结点的权值是它两个孩子之和)。见 5.5 哈夫曼树与并查集。
链接
- 📕 返回:数据结构代码板子
- ⬅️ 上一篇:靠递归返回值的题
- ➡️ 下一篇:表达式树转中缀表达式
- 🔗 按层处理:层序遍历与按层处理
- 🔗 算法题答题三段式