带权路径长度 层次遍历

来源:互联网 发布:雷电网络 价格 编辑:程序博客网 时间:2024/05/29 17:52

思路:层次遍历

带权路径长度:结点具有权值,从该结点到根之间的路径长度乘以结点的权值,就是该结点的带权路径长度。

叶子结点的带权路径长度:结点到根之间的路径长度(所在层数-1)乘以结点的权值。

树的带权路径长度(WPL):树的所有叶子结点的带权路径长度之和。

树的带权路径长度记为WPL = (W1*L1 + W2*L2 + W3*L3 + ... + Wn*Ln),N个权值Wi(i = 1, 2, ...n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i = 1, 2, ...n)。

随便复习哈夫曼树:

可以证明哈夫曼树的WPL是最小的。WPL是衡量一个带权二叉树优劣的关键。无论如何,对于n个带权节点,可以用他们作为叶节点构造出一颗最小WPL值得树,并称满足这个条件的二叉树为哈夫曼树。

【例】给定4个叶子结点a,b,c和d,分别带权7,5,2和4。构造如下图所示的三棵二叉树(还有许多棵),它们的带权路径长度分别为:

(a)WPL = 7 * 2 + 5 * 2 + 2 * 2 + 4 * 2 = 36

(b)WPL = 7 * 35 * 3 2 * 1  4 * 2 = 46

(c)WPL = 7 * 1  5 * 22 * 3 4 * 3 = 35

其中(c)树的WPL最小,可以验证,它就是哈夫曼树。

#include <iostream>#include <queue>using namespace std;class TreeNode{private:char val;TreeNode* left;TreeNode* right;public://二叉树的初始化函数 TreeNode* Create_TreeNode(){TreeNode* T = new TreeNode;char ch;cin >> ch;if (ch == '#'){                                                  //“#”是结束标志 T = NULL;}else{T->val = ch;                                               //对当前结点初始化 T->left = Create_TreeNode();                            //递归构造左子树 T->right = Create_TreeNode();                            //递归构造右子树 }return T;}int WPL(TreeNode* root) {queue<TreeNode*> que;//处理数据队列  vector<int> temp;// 存储每一层数据   TreeNode* last = root;TreeNode* nLast = root;que.push(root);int level = 1;//level代表层数 int sum = 0; //带权路径长度之和    while (!que.empty()){TreeNode* proot = que.front();que.pop();temp.push_back(proot->val);if (proot->left){ //左孩子非空入队que.push(proot->left);nLast = proot->left;}if (proot->right){ //右孩子非空入队que.push(proot->right);nLast = proot->right;}if (proot == last){ //队头指针是该层最后一个结点时 level++;//层数加一last = nLast;//最后一个结点指针下移到下一层的最后一个结点 temp.clear();}if (proot->left == NULL && proot->right == NULL){int weight = proot->val - '0';sum += (level - 1)*weight; //层数level,该层的每个叶节点的带权路径长度 = (level - 1)*weight}}return sum;}};int main(){cout << "请初始化二叉树:" << endl;TreeNode Tree;TreeNode* T1 = Tree.Create_TreeNode();cout << "叶子节点的带权路径之和为:" << endl;int wpl = Tree.WPL(T1);cout << wpl << endl;system("pause");return 0;}