帶權路徑長度 層次遍歷
阿新 • • 發佈:2019-01-27
思路:層次遍歷
帶權路徑長度:結點具有權值,從該結點到根之間的路徑長度乘以結點的權值,就是該結點的帶權路徑長度。
葉子結點的帶權路徑長度:從葉結點到根之間的路徑長度(所在層數-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是衡量一個帶權二叉樹優劣的關鍵。
【例】給定4個葉子結點a,b,c和d,分別帶權7,5,2和4。構造如下圖所示的三棵二叉樹(還有許多棵),它們的帶權路徑長度分別為:
(a)WPL = 7 * 2 + 5 * 2 + 2 * 2 + 4 * 2 = 36
(b)WPL = 7 * 3 + 5 * 3 + 2 * 1 + 4 * 2 = 46
(c)WPL = 7 * 1 + 5 * 2 + 2 * 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; }