C++二叉树计算带权路径长度(WPL)的算法

二叉树计算带权路径长度(WPL)的算法

更多内容请访问点击我的主页

题目 :

二叉树的带权路径长度是二叉树中所有叶子结点的带权路径长度之和。给定二叉链表的存储的结点结构为

leftweightright

weight存储的是叶子结点的非负权值。设计算法求二叉树的带权路径长度WPL。

WPL = ∑ 叶子结点的权值 × 结点到根结点的分支个数 1

例如:
在这里插入图片描述

非递归算法

  1. 算法思想:根据公式,需要记录每个结点到根结点的分支个数,这个过程通过对树进行广度遍历(借助队列)进行记录。
    在非叶子结点weight初值为-1,叶子结点初值设为非负权值。
    最后对队列进行逐个访问,如果weight != -1,那就计算该点。
wpl += (Q[i].p->weigth) * (Q[i].p->lno - 1);  //WPL公式代码

这里改造队列的结点结构

typedef struct
{
	LBTree* p;   //树的结点
	int lno;     //结点深度
}Queue;
  1. 伪代码
typedef struct
{
	LBTree* p;
	int lno;
}Queue;
int WPL(LBTree* lbt)
{
	Queue Q[maxSize];
	int front,rear;
	front = rear = 0;
	int Lno = 1;
	LBTree* q = lbt;
	Q[rear].p = q;
	Q[rear].lno = Lno;
	rear++;
	while (front != rear)
	{
		q = Q[front].p;
		Lno = Q[front].lno;
		front++;
		if (q->lchild != NULL)
		{
			Q[rear].p = q->lchild;
			Q[rear].lno = Lno + 1;
			rear++;
		}
		if (q->rchild != NULL)
		{
			Q[rear].p = q->rchild;
			Q[rear].lno = Lno + 1;
			rear++;
		}
	}
	int wpl = 0;
	for (int i = 0; i < rear; i++)
	{	
		if (Q[i].p->weigth != -1)
			wpl += (Q[i].p->weigth) * (Q[i].p->lno - 1);
	}
	return wpl;
}

递归算法 (推荐)

  1. 算法描述:本算法采用的是统计叶子结点算法基础上改造而来的。只是在参数列表定义了结点到根的分支个数。进行一个递归计算。统计结点数在个人主页有相关算法。
  2. 代码如下:
int WPLrec(LBTree* lbt,int n)
{
	int wpl = 0;
	if (lbt != NULL)
	{
		if (lbt->lchild == NULL && lbt->rchild == NULL)
			wpl += n * lbt->weigth;
		wpl += WPLrec(lbt->lchild, n + 1);
		wpl += WPLrec(lbt->rchild, n + 1);
	}
	return wpl;
}

  1. 结点到根结点的分支个数 = 该结点的深度 - 1。 ↩︎

这里提供一种基于贪心算法C++实现: ```c++ #include <iostream> #include <vector> #include <queue> using namespace std; // 定义二叉树节点结构体 struct TreeNode { int val; // 节点值 TreeNode* left; // 左子节点 TreeNode* right; // 右子节点 TreeNode(int x) : val(x), left(NULL), right(NULL) {} }; // 定义节点比较函数,用于优先队列排序 struct cmp { bool operator() (TreeNode* a, TreeNode* b) { return a->val > b->val; } }; // 构造最小外部路径长度的扩充二叉树 TreeNode* createHuffmanTree(vector<int>& weights) { priority_queue<TreeNode*, vector<TreeNode*>, cmp> pq; // 定义小根堆 for (int i = 0; i < weights.size(); i++) { pq.push(new TreeNode(weights[i])); // 将节点加入小根堆 } while (pq.size() > 1) { TreeNode* left = pq.top(); // 取出堆顶节点,即值最小的节点 pq.pop(); TreeNode* right = pq.top(); pq.pop(); TreeNode* parent = new TreeNode(left->val + right->val); // 将左右子节点合并,构造出父节点 parent->left = left; parent->right = right; pq.push(parent); // 将父节点加回小根堆中 } return pq.top(); // 最终堆中只剩下一个根节点,即为构造好的扩充二叉树 } // 计算外部路径长度 int getWeightedExternalPathLength(TreeNode* root, int depth) { if (root == NULL) { return 0; } if (root->left == NULL && root->right == NULL) { // 叶子节点 return depth * root->val; } return getWeightedExternalPathLength(root->left, depth + 1) + getWeightedExternalPathLength(root->right, depth + 1); } int main() { vector<int> weights = {1, 2, 3, 4, 5}; TreeNode* root = createHuffmanTree(weights); int wpl = getWeightedExternalPathLength(root, 0); cout << "外部路径长度为:" << wpl << endl; return 0; } ``` 在该代码中,我们首先定义了一个二叉树节点结构体 `TreeNode`,包含节点值 `val`、左子节点指针 `left` 和右子节点指针 `right`。然后,我们定义了一个节点比较函数 `cmp`,用于优先队列排序,将节点按照值从小到大排列。 接着,我们实现了构造最小外部路径长度的扩充二叉树的函数 `createHuffmanTree`。首先,我们定义了一个小根堆 `pq`,将所有节点加入小根堆。然后,每次从小根堆中取出两个值最小的节点,将它们合并成一个父节点,再将父节点加入小根堆中。最终,小根堆中只剩下一个根节点,即为构造好的扩充二叉树。 最后,我们实现了计算外部路径长度的函数 `getWeightedExternalPathLength`。我们采用递归的方式计算外部路径长度。如果当前节点是叶子节点,直接返回节点值乘以当前深度。否则,递归计算左右子树的外部路径长度之和。 在 `main` 函数中,我们构造了一个值数组 `{1, 2, 3, 4, 5}`,并调用 `createHuffmanTree` 函数构造出外部路径长度最小的扩充二叉树。然后,调用 `getWeightedExternalPathLength` 函数计算外部路径长度,并输出结果。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值