每日一題(9)——Huffman編碼(貪心)

來源:互聯網
上載者:User

哈夫曼編碼是典型的貪心問題,不斷地通過局部最優,最終計算全域最優結果。

 

1951年,霍夫曼和他在MIT資訊理論的同學需要選擇是完成學期報告還是期末考試。導師Robert
M. Fano給他們的學期報告的題目是,尋找最有效二進位編碼。由於無法證明哪個已有編碼是最有效,霍夫曼放棄對已有編碼的研究,轉向新的探索,最終發現了基於有序頻率二叉樹編碼的想法,並很快證明了這個方法是最有效。

由於這個演算法,學生終於青出於藍,超過了他那曾經和資訊理論創立者克勞德·香農共同研究過類似編碼的導師。霍夫曼使用自底向上的方法構建二叉樹,避免了次優演算法Shannon-Fano編碼的最大弊端──自頂向下構建樹。

為每個符號建立一個葉子節點,並加上其相應的發生頻率

  1. 當有一個以上的節點存在時,進行下列迴圈:

    1. 把這些節點作為帶權值的二叉樹的根節點,左右子樹為空白
    2. 選擇兩棵根結點權值最小的樹作為左右子樹構造一棵新的二叉樹,且至新的二叉樹的根結點的權值為其左右子樹上根結點的權值之和。
    3. 把權值最小的兩個根節點移除
    4. 將新的二叉樹排入佇列中.
  2. 最後剩下的節點暨為根節點,此時二叉樹已經完成。

樣本

Huffman Algorithm


符號 A B C D E
計數 15 7 6 6 5
機率 0.38461538 0.17948718 0.15384615 0.15384615 0.12820513

在這種情況下,D,E的最低頻率和分配分別為0和1,分組結合機率的0.28205128。現在最低的一雙是B和C,所以他們就分配0和1組合結合機率的0.33333333在一起。這使得BC和DE所以0和1的前面加上他們的代碼和它們結合的機率最低。然後離開只是一個和BCDE,其中有首碼分別為0和1,然後結合。這使我們與一個單一的節點,我們的演算法是完整的。


 

 

 

可得A代碼的代碼長度是1位元,其餘字元是3位元。

字元 A B C D E
代碼 0 100 101 110 111

    Entropy: 哈夫曼演算法實現

//參考sophia_qing的priotity_queue做法#include <iostream>#include <queue>#include <vector>#include <map>#include <iterator>#include <string>using namespace std;#define Nchar 8 //using 8 bit to describe all symbols#define Nsymbols 1<<Nchar //can describe 256 symbols totally (include a-z, A-Z)typedef vector<bool> Huff_code;map<char, Huff_code> Huff_dic;class Hnode {public:char data;float fre;Hnode *left, *right;Hnode(){data='\0'; fre=0; left=NULL; right=NULL;}Hnode(char c, float f, Hnode* l, Hnode* r){data=c; fre=f; left=l; right=r;}~Hnode(){delete left; delete right;}bool isLeaf(){ return !left&&!right;}};//只能為類類型或枚舉類型的運算元定義重載操作符;//在把操作符聲明為類的成員時,至少有一個類或枚舉類型的參數按照值或者引用的方式傳遞;//因此不能在class Hnode內直接重載;(prepare for pointer sorting);class compare_node{public:bool operator () (Hnode* n1, Hnode* n2 ){return n1->fre > n2->fre;}};Hnode* bulidHtree(int *frequency){priority_queue<Hnode*, vector<Hnode*>, compare_node> Qtree;for(int i=0; i<Nsymbols; i++){if(frequency[i])Qtree.push(new Hnode( (char) i, frequency[i], NULL, NULL));}while(Qtree.size()>1){//不斷定義Hnode* Hnode* lc = Qtree.top();Qtree.pop();Hnode* rc =Qtree.top();Qtree.pop();Hnode* parents = new Hnode((char) 256, lc->fre + rc->fre, lc,rc);Qtree.push(parents);//最後一次是把根節點push進Qtree中}return Qtree.top();//最後返回的是Haffuman樹的根節點}void Huffman_coding(Hnode* root, Huff_code& curcode){if (root->isLeaf()){Huff_dic[root->data]=curcode;return;}Huff_code lcode = curcode;//定義左孩子的編碼;Huff_code rcode = curcode;//定義右孩子的編碼;lcode.push_back(false);rcode.push_back(true);Huffman_coding(root->left, lcode);Huffman_coding(root->right, rcode);}int main(){int freq[Nsymbols] = {0};char* c = "compress this is the string  into Huffman code";while(*c != '\0')freq[*c++]++ ;Hnode *root = bulidHtree(freq);Huff_code nullcode;nullcode.clear();Huffman_coding(root, nullcode);for(map<char, Huff_code>::iterator it = Huff_dic.begin(); it!=Huff_dic.end(); it++){cout<<(*it).first<<'\t';copy(it->second.begin(), it->second.end(), ostream_iterator<bool>(cout));cout<<endl;}}

 

 

Referance:

1. http://blog.csdn.net/abcjennifer/article/details/8020695

2. http://www.binaryessence.com/dct/en000042.htm3. http://zh.wikipedia.org/zh/%E9%A6%99%E5%86%9C-%E8%8C%83%E8%AF%BA%E7%BC%96%E7%A0%81#.E5.93.88.E5.A4.AB.E6.9B.BC.E7.AE.97.E6.B3.954. http://www.stringology.org/DataCompression/sh/index_en.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.