任務描述
本關任務:編程實現哈夫曼樹的的構建,並求其帶權路徑長度
相關知識
完成本關你需要了解一下內容: 1、哈夫曼樹的定義; 2、哈夫曼樹的存儲結構; 3、哈夫曼樹的構造算法; 4、哈夫曼樹帶權路徑長度計算方法
1、哈夫曼樹的定義 給定一組具有確定權值的葉子結點,構造出帶權路徑長度最小的二叉樹即為該組葉子結點所構成的哈夫曼樹。 2、哈夫曼樹的存儲結構 哈夫曼樹可以采用雙親孩子仿真指針存儲結構進行存儲,其定義如下:
typedef struct //定義雙親孩子仿真指針結構體
{
datatype data; // 本關所求解問題與結點的值無關,這個數據項可忽略
int weight ;
/* 用來存放各個結點的權值*/
int parent, lchild,rchild ; /* 雙親孩子仿真指針*/
}HTNode, * HuffmanTree; //n個葉子結點的哈夫曼樹共有2*n-1個結點
HuffmanTree=(HTNode *) malloc(sizeof(HTNode)*2*n-1);
3、哈夫曼樹構造的算法 初始化長度為2n-1的仿真指針中各葉子結點的初始值(包括parent、lchild、rchild)。 for(i=n;i<2n-1;i++)//合並樹 { 在parent值為-1的結點中找出weight值最小的兩個結點node1和node2 用數組的第i個結點作為根結點來合並node1和node2。(即修改node1和node2的parrent值,修改第i個結點的weight、lchild、rchild值) } 例如:5個結點權值分別為3,4,5,6,12的結點,初始化9個結點的哈夫曼數組如下圖1所示,構建完成的哈夫曼樹如下圖2所示,其圖示表示入下圖3所示。 圖1初始狀態
圖2終止狀態
圖3哈夫曼樹的圖示表示 4、哈夫曼樹帶權路徑長度計算方法 帶權路徑長度:從二叉樹的根結點到二叉樹中所有葉結點的路徑長度與相應葉結點權值的乘積之和稱作該二叉樹的(WPL),即:
同時, WPL=所有非葉子結點的權值之和。 圖3所表示的哈夫曼樹的帶權路徑權值
WPL=12+(4+3+5+6)*3=66 (根據葉子結點的帶權路徑權值計算) =20+18+7+11=66 (根據非葉子結點的權值計算)
編程要求
根據提示,在右側代碼編輯器中,補充完整initHaffTree
、creatHaffTree
、WPL
等函數,完成根據輸入的葉子結點權值,構造相應的哈夫曼樹,求其帶權路徑長度,並輸出。
輸入輸出說明
輸入為一組測試用例占一行,先輸入葉子結點個數n(1<=n<=100),然后輸入n個葉子葉子結點的int型的權值,輸出由這n個葉子結點構成的哈夫曼樹的帶權路徑權值 例: 輸入 5 3 4 5 6 12 66
不用建樹
#include<iostream> #include<stdio.h> #include<queue> using namespace std; priority_queue<int,vector<int>,greater<int> > Q; int main(){ int N; scanf("%d",&N); while(!Q.empty()) Q.pop(); for(int i = 0; i < N; i++){ int x; scanf("%d",&x); Q.push(x); } int ans = 0; while(!Q.empty()&&Q.size()>1){ int a = Q.top(); Q.pop(); int b = Q.top(); Q.pop(); ans += a + b; Q.push(a+b); } printf("%d\n",ans); }
建樹的以后再補。。