考研数据结构(每日一题)
题目:二叉树的带权路径长度(WPL)是二叉树中所有叶结点的带权路径长度之和,给定一棵二叉树T,采用二叉链表存储,结点结构为(left,weight,right),其中叶结点的weight域保存该结点的非负权值,设root为指向T的根结点的指针,请设计求T的WPL的算法。
算法思想:
二叉树的带权路径长度为每个叶结点的深度与权值之和的总和,可以使用先序遍历或层次遍历。
先序遍历使用一个static变量记录wpl,把每个结点的深度作为递归函数的一个参数传递。
- 若该结点是叶结点,则变量wpl加上该结点的深度与权值之积
- 若该结点非叶结点,则左子树不为空时,对左子树调用递归算法,右子树不为空,对右子树调用递归算法,深度参数均为结点的深度加1
- 最后返回计算wpl即可
层次遍历是使用队列,并记录当前的层数
- 当遍历到叶结点时,累计wpl
- 当遍历到非叶结点时,把该结点的子树加入队列
- 当某结点为该层最后一个结点时,层数自增加1
- 队空时,遍历结束,返回wpl
完整代码:
先序遍历:
typedef struct BiTNode{
int weight;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
int WPL(BiTree root){
return wpl_PreOrder(root,0);
}
int wpl_PreOrder(BiTree root,int deep){
static int wpl = 0; //定义变量存储wpl
if(root -> lchild == NULL && root -> rchild == NULL){ //若为叶结点,则累计wpl
wpl += deep * root -> weight;
}
if(root -> lchild != NULL){ //若左子树不空,则对左子树递归
wpl_PreOrder(root -> lchild,deep + 1);
}
if(root -> rchild != NULL){ //若右子树不空,则对右子树递归
wpl_PreOrder(root -> rchild,deep + 1);
}
return wpl;
}
层次遍历:
# define MaxSize 100 //设置队列最大容器
int wpl_LevelOrder(BiTree root){
BiTree q[MaxSize]; //声明队列
int end1,end2; //end1为头指针,end2为尾指针,队列最多容纳MaxSize-1个元素
end1 = end2 = 0; //头指针指向队头元素,尾指针指向队尾的后一个元素
int wpl = 0,deep = 0; //初始化wpl和深度
BiTree lastNode; //lastNode记录当前层的最后一个结点
BiTree newlastNode; //newlastNode用来记录下一层的最后一个结点
lastNode = root; //lastNode初始化为根结点
newlastNode = NULL; //初始化为空
q[end2 ++] = root; //根结点入队
while (end1 != end2) //层次遍历,若队列不空则循环
{
BiTree t = q[end1 ++]; //拿出队列中的头一个元素
if(t -> lchild == NULL && t -> rchild == NULL){
wpl += deep * t -> weight;
}
if(t -> lchild != NULL){ //若非叶结点,则让左结点入队
q[end2 ++] = t -> rchild;
newlastNode = t -> lchild;
} //并设下一层的最后一个结点为该结点的左结点
if(t -> rchild != NULL){ //处理叶结点
q[end2 ++] = t -> rchild;
newlastNode = t -> rchild;
}
if(t == lastNode){ //若该结点为本层最后一个结点,则更新lastNode
lastNode = newlastNode;
deep += 1; //层数加1
}
}
return wpl; //返回
}