1. 程式人生 > 其它 >貪心演算法 --- 例題2.哈夫曼編碼問題

貪心演算法 --- 例題2.哈夫曼編碼問題

一.問題描述

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努力!