資料結構-練習7 huffman編碼

來源:互聯網
上載者:User

        huffman編碼是重要的編碼方式之一。作為一名程式員,應該要做到融會貫通,因此我在網上搜些資料看,發現幾乎沒有適合我等菜鳥級的文章,不是沒有圖解,就是不說明為什麼要引入huffman編碼,稀裡糊塗,於是自己整理了一下,歡迎諸君拍磚。

           

        

        Huffman是一種無損壓縮方法:所謂無損就是不會有資訊丟失,可以100%恢複原訊號,像奈奎斯特恢複就是有損了;所謂壓縮,就是可以佔有更少的儲存空間。

       比如要發送三個字元:S1,S2,S3。我們可以這樣編碼:00,01,10。當然這是小資料,如果要發送的圖片或是視頻呢?比如一副高清圖片,10M,在區域網路上即使可以達到理論的10Mbps,也要1s,沒法滿足視頻的最低幀頻24fps。因此壓縮非常重要,當然採用的壓縮很多,huffman只是早期的一種而已,這就是Huffman的背景。

      現在來看看它的原理:先不聯絡最優二叉樹那套東西。基本原理是根據字元出現的機率確定其碼子。即高機率的少碼字,低機率的多碼字。     舉個例子吧:

                         

                                                                                                             

                                                                                                                                                    圖 1

         結合:

                        A B C D E 5個字元及其出現的機率。過程很簡單:

 

                        First:          從上到下,根據機率由大到小排列;

 

                        Second:    倆倆合并,先合并機率低的,比如D E 機率最低,合并之,得到機率0.1,再尋找機率最低的倆部分,發現是C 和 DE,合并之,合并後,

                       標出新的 機率值 ,中紅色圈起來的部分,直到合并完全;

 

                       Third:         標出0或1。中藍色部分,低機率的給0(1也可以),機率相等的,就0和1隨意了;

 

                       Last:            得到編碼值:A:1,B:10;C:100; D:1000; E:0000。

 

 

          整個編碼過程完畢。以上就是Huffman編碼的大體過程。好了,感受完其最基本的過程。我們再來完成最優二叉樹(赫夫曼樹)的代碼編寫,分為倆部分:第一部分為基本概念,第二部分為:代碼的實現,並有測試結果。

         

          Huffman 樹狀目錄:帶權路徑最短的樹。所謂帶權路徑,就是從該節點到樹根的長度與節點上的權的乘積                                                                                                                                                    

 

                                                                                                                                                圖 2

 

 

 

          那麼樹的帶權路徑就是所有節點的帶權路徑之和,公式表示:         

如:套公式:6*1+4*2+1*3+2*3

        有了一開始部分的介紹,huffman二叉樹的構造就很簡單了,步驟:

          1,找到權重最小的倆節點,合并最為一個新的節點,比如上面D,E合并,得到一個新的節點,暫且叫  做DE,則D,E作為子節點,DE作為父節點;

           2,以DE代替D和E,DE的權重為D和E之和,重新第一步,直到所有節點都加入到二叉樹中。

           3,對於權重小的節點附0(或1),對於權重大的節點附1(或0)。

           如把圖1huffman的計算過程變成二叉樹的 圖形如下:

                                                                                                                       

                                                                                                                                                             圖 3

      讀者,把一開始的圖1 ,旋轉過來跟圖 2 是一樣的,因為原理一樣。注意:huffman分葉節點為n,需要2*n-1個節點來構成二叉樹,樹的節點的度為2(除去分葉節點)。

      第二部分:以一個例子開始:  權重W={5,29,7,8,14,23,3,11}.n=8.此例子為嚴蔚敏第159頁的例子。

               上代碼:                                                                                                                                                                                                        

/*Coder  Information      e_mail:shenganbeiyang@163.com      QQ:501968942*/#ifndef HUFF_H#define HUFF_H#include<string>//定義一個結構體,包括節點的父節點和左右子節點//字元的個數const int maxnum=30;typedef struct Tnode{ char val; int weight; int parent; int lchild; int rchild;}huffmanNode ,*huffmanTree;class huffmanCoding{public://初始化最優二叉樹(哈夫曼樹)huffmanCoding(huffmanNode * hn,int length);    //編碼過程    void  Selection(int);void  Encode(int);    //解碼過程//    stringdeCode();//deconstruction function~huffmanCoding(){for(int i=0;i<length;++i)delete HC[i];delete [] HC;}; char** HC;//儲存編碼資訊private:huffmanNode InitData[maxnum];//char** HC;//儲存編碼資訊int length;};//constructor function.初始化二叉樹inline huffmanCoding::huffmanCoding(huffmanNode * hn,int length_){   HC=new char*[length_];//(sizeof(char*)*length);//new (char*)[length];   length=length_;   int i;   for( i=0;i<length;++i)   {    InitData[i]=hn[i];InitData[i].parent=-1;InitData[i].rchild=-1;InitData[i].lchild=-1;     }   for(int j=i;j<2*length;++j)   {InitData[j].lchild=-1;InitData[j].rchild=-1;InitData[j].weight=-1;InitData[j].val='0';InitData[j].parent=-1;      }}//編碼huffman二叉樹inline void huffmanCoding::Selection(int codedlength){int pos_1,pos_2;pos_1=pos_2=-1;int i;    for( i=0;i<codedlength;++i){if(InitData[i].parent==-1){pos_1=i;    break; }}    for(int k=pos_1+1;k<codedlength;++k){if(InitData[k].weight<InitData[pos_1].weight&&InitData[k].parent==-1){ pos_1=k;}}    for(int j=0;j<codedlength;++j)    {if(InitData[j].parent==-1&&j!=pos_1){pos_2=j;    break;}    }     for(int j=pos_2+1;j<codedlength;++j) {   if(InitData[j].weight<InitData[pos_2].weight&&InitData[j].parent==-1&&j!=pos_1) {   pos_2=j;  }       } if(InitData[pos_1].weight<InitData[pos_2].weight) { InitData[codedlength].lchild=pos_1; InitData[codedlength].rchild=pos_2; InitData[pos_1].parent=codedlength; InitData[pos_2].parent=codedlength; InitData[codedlength].weight=InitData[pos_1].weight+InitData[pos_2].weight; } else {          InitData[codedlength].lchild=pos_2; InitData[codedlength].rchild=pos_1; InitData[pos_1].parent=codedlength; InitData[pos_2].parent=codedlength; InitData[codedlength].weight=InitData[pos_1].weight+InitData[pos_2].weight;  }     }inline void huffmanCoding::Encode(int len){         for(int i=len;i<2*len-1;++i) {     Selection(i); }         char*dc=new char[length];     for(int m=0;m<length;++m)     dc[m]='\0';          int start=0; int tmp; int p; for(int m=0;m<length;++m) { for(tmp=m,p=InitData[m].parent;p!=-1;tmp=p,p=InitData[p].parent) { if(InitData[p].lchild==tmp) dc[start++]='0'; else dc[start++]='1';      }  dc[start]='\0';  HC[m]=new char[length];  start=0;          strcpy(HC[m],dc); }delete [] dc;}#endif

測試代碼:

#include"huff.h"#include<iostream>using namespace std;int main(){     int i=0;huffmanTree ht=new huffmanNode[8];for(;i<8;++i){    ht[i].val='a'+i;}ht[0].weight=5;ht[1].weight=29;ht[2].weight=7;ht[3].weight=8;ht[4].weight=14;ht[5].weight=23;ht[6].weight=3;ht[7].weight=11;huffmanCoding hc(ht,8);hc.Encode(8);for(int i=0;i<8;++i)cout<<hc.HC[i]<<endl;return 0;}

測試結果,即編碼結果為:

  

大家可能發現 與書上的結果不一樣,嚴的書是 左節點必須為葉子節點,並且強制附0,我認為這不正確。huffman的定義不是這樣的,如有異議可交流。

 

        

                        

                            

 

                         

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.