貪心演算法 --- 例題2.哈夫曼編碼問題
阿新 • • 發佈:2021-12-21
一.問題描述
Huffman樹在編碼中有著廣泛的應用。在這裡,我們只關心Huffman樹的構造過程。
樹的帶權路徑長度:樹中所有葉子結點的帶權路徑長度之和,通常記作:WPL = Σwi*li (i=1~n)
哈夫曼樹,Huffman樹定義:在權為w1,w2,…,wn的n個葉子結點的所有二叉樹中,帶權路徑長度WPL最小的二叉樹稱為赫夫曼樹或最優二叉樹。
本題任務:對於給定的一個數列,現在請你求出用該數列構造Huffman樹的總費用。
二.解題思路
哈夫曼樹的構造(哈夫曼演算法)
- 1.根據給定的n個權值{w1,w2,…,wn}構成二叉樹集合F={T1,T2,…,Tn},其中每棵二叉樹Ti中只有一個帶權為wi的根結點,其左右子樹為空.
- 2.在F中選取兩棵根結點權值最小的樹作為左右子樹構造一棵新的二叉樹,且置新的二叉樹的根結點的權值為左右子樹根結點的權值之和.
- 3.在F中刪除這兩棵樹,同時將新的二叉樹加入F中.
- 4.重複2、3,直到F只含有一棵樹為止.(得到哈夫曼樹)
程式碼如下:
// 哈夫曼編碼貪心演算法實現 // 輸入格式 // 輸入的第一行包含一個正整數n(n<=100)。 // 接下來是n個正整數,表示p0, p1, …, pn-1,每個數不超過1000。 // 輸出格式 // 輸出用這些數構造Huffman樹的總費用。 #include<bits/stdc++.h> using namespace std; int Huffman(int *a, int n) { int ans = 0; int pos = 0; int temp_n = n; while(n>1) { // sort(a+pos, a+temp_n); sort(a, a+temp_n); ans = ans + (a[pos] + a[pos+1]); a[pos+1] = a[pos] + a[pos+1]; pos++; n--; } return ans; } int Huffman2(int a[], int n) { int ans = 0; sort(a, a+n); for(int i=0; i<n-1; i++) { ans += (a[i]+a[i+1]); a[i+1] += a[i]; sort(a, a+n); } return ans; } int main() { int t, n; cout<<"輸入資料組數:"; cin>>t; while (t--) { cout<<"輸入陣列大小:"; cin>>n; int a[n]; cout<<"輸入陣列元素:"; for(int i=0; i<n; i++) cin>>a[i]; cout<<"最小哈夫曼構造代價:"<<Huffman2(a, n)<<endl; } system("pause"); return 0; }
執行結果:
參考畢方明老師《演算法設計與分析》課件.
歡迎大家訪問個人部落格網站---喬治的程式設計小屋,和我一起為大廠offer努力!