题目01
题目分析
1、什么是WPL?
根究题目要求WPL指的是二叉树的带权路径长度,当然笼统的说,WPL便是二叉树中从根节点到某一个固定的叶子结点之间所走的路径与最终的叶子结点权值的乘积的总和。
文字可能表达的意思不深刻,还是画图说话,求如下图所示的二叉树的WPL的大小。
有了上述的对WPL的计算概述,针对其中存在的计算逻辑,我们对其进行代码的编写思路分解:
1、WPL的计算首先是要建立在叶子节点的基础上
第一个问题:如何求一颗二叉树的叶子节点?
相信这个问题,在看过前面的树代码文章后,第二题—如何求叶子节点
对于叶子结点的递归求法是非常熟悉了。这里我们给出递归求解叶子节点代码:
void GetSimpleNode(BiTree * root){
if(root == NULL){
return ;
}
if(root != NULL){
if(root->left== NULL && root->right== NULL){
//找到了叶子节点
}
GetSimpleNode(root->left);
GetSimpleNode(root->right);
}
}
解决了如何寻找叶子结点的问题,即也就找到了当前叶子结点的权值
下一步便是对从根节点如何到达根节点的路径长度进行判断求解。
第二个问题:如何求解根节点到叶子结点的路径长度
对于上述问题,我们采用递归的方式对其进行求解,
1. 若根节点为NULL,则返回0;
2. 若跟结点不为空。那么若左子树不为null,则设置一个depth作为路径长度,并+1,(表示进入左子树)
3. 若右子树不为空则进入右子树,depth+1,表示进入下一层。
结合以上的思路,给出递归求解二叉树的代码:
int GetSimpleNodeDepth(BiTree *root,int depth){
if(root == NULL){
return 0;
}
if(root!=NULL){
if(root->left==NULL && root->right==NULL){
//这里便是找到了叶子结点
printf("%d",depth);//输出高度
}
if(root->left!= NULL){
GetSimpleNode(root->left,depth+1);//递归求左子树
}
if(root->right!= NULL){
GetSimpleNode(root->right,depth+1);//求解右子树
}
}
}
根据以上的问题,分步骤进行分析, 结合求解叶子结点和根节点到叶子节点的路径长度的两个步骤的代码分析,这里我们对其进行求解第三步求解WPL
第三个问题:求解WPL思路
- 设置一个变量,这里命名为WPL,并给其初始化为0;
- 每次递归到我们想要的位置后->>>即叶子结点的位置
- 对其进行求和运算,代码实现如下:
int WPL = 0;
if(){
//找到了我们需要的位置
WPL = WPL+(root->weight)*depth;
}
结合上述的三步骤对其进行结合,给出我们最终的解题函数
(注意:这里是编写的解题函数,因为题目要求我们给出数据结构定义,并可执行代码因此还需要设置一个启动函数)
解题函数代码
结构体代码:
typedef struct TreeNode{
int weight;//数据域
struct TreeNode *left,*right;//指针域
}*BiTree;
函数代码:
int GetTreeWPLFun(BiTree *root,int depth){
int WPL = 0;//作为返回结果
if(root == NULL){//若根节点为NULL,则返回0
return 0;
}
if(root != NULL){
//进行递归求解叶子结点
if(root ->left == NULL && root->right == NULL){
WPL = WPL + (root->weight)*depth;//求解WPL
//return WPL;
//注意!!!return WPL;这一条语句,不可以加在这,
//因为当前是进行求和运算的,只能访问完所有的叶子结点后才可以返回最后的结果。
}
//若左子树不为空,则进行递归求解
if(root->left != NULL){
GetTreeWPLFun(root->left,depth+1);
}
//若右子树不为空,那么递归求右子树的wpl
if(root->right != NULL){
GetTreeWPLFun(root->right,depth+1);
}
return WPL;//最后返回该函数的结果值
}
return 0;//与函数的返回值无关
}
给出了上述的操作函数后,想一下,这个代码里面的depth参数是几?
我们无法通过上述的代码对depth进行初始化,因此我们需要再添加一个启动函数
第四个问题:启动函数代码
//启动函数
int GetTreeWPLResult(BiTree *root){
return GetTreeWPLFun(root,0);//返回并初始化depth为0
}
结合上述的四个问题的解答,我们给出最终的答题代码:
//结构体
typedef struct TreeNode{
int weight;//数据域
struct TreeNode *left,*right;//指针域
}*BiTree;
//执行函数
int GetTreeWPLFun(BiTree *root,int depth){
int WPL = 0;//作为返回结果
if(root == NULL){//若根节点为NULL,则返回0
return 0;
}
if(root != NULL){
//进行递归求解叶子结点
if(root ->left == NULL && root->right == NULL){
WPL = WPL + (root->weight)*depth;//求解WPL
//return WPL;
//注意!!!return WPL;这一条语句,不可以加在这,
//因为当前是进行求和运算的,只能访问完所有的叶子结点后才可以返回最后的结果。
}
//若左子树不为空,则进行递归求解
if(root->left != NULL){
GetTreeWPLFun(root->left,depth+1);
}
//若右子树不为空,那么递归求右子树的wpl
if(root->right != NULL){
GetTreeWPLFun(root->right,depth+1);
}
return WPL;//最后返回该函数的结果值
}
return 0;//与函数的返回值无关
}
//启动函数
int GetTreeWPLResult(BiTree *root){
return GetTreeWPLFun(root,0);//返回并初始化depth为0
}