哈夫曼編碼及其解碼


添加注釋版本:

/* cout<<i<<endl<<" 結點 | data | weight | lchild | rchild | parent "<<endl; for(int i=1;i<=m;++i) { cout<<i<<" | "<<HT[i].data<<" | "<<HT[i].weight<<" | "<<HT[i].lchild<<" | "<<HT[i].rchild<<" | "<<HT[i].parent<<endl; } */ #include<iostream> #include<stdio.h> #include<string> #include<cstring> #include<algorithm>
#define MAX 0x3f3f3f3f 
using namespace std; typedef struct { char data; int weight; int parent; int lchild; int rchild; bool tag; }Huffnode,*HuffmanTree; typedef struct { string *code;//存放字符的編碼 
    char *data;//存放字符 
    int num;//存放一共有多少字符 
}HuffmanCode; void DisplayHuffmanCode(HuffmanCode &HC,int n) { for(int i=0;i<n;++i) { cout<<HC.code[i]<<endl; } } void Select(HuffmanTree &HT,int index, int &s1, int &s2) { int min1=MAX; int min2=MAX; for(int i=1;i<=index;++i) { if(HT[i].parent==0&&HT[i].tag) { if(HT[i].weight<min1) { s1=i; min1=HT[i].weight; } } } HT[s1].tag=0;//表明此節點已經被選中過 
    for(int i=1;i<=index;++i) { if(HT[i].parent==0&&HT[i].tag) { if(HT[i].weight<min2) { s2=i; min2=HT[i].weight; } } } HT[s2].tag=0; } void CreatHuffmanTree(HuffmanTree &HT,int n) { /*n:待編碼數有多少*/
    if(n<=1)return; int m=2*n-1; //計算節點個數
    HT=new Huffnode[m+1];//0號單元未用,HT[m]表示根結點,從1開始存放數據 //初始化哈夫曼表
    for(int i=1;i<=m;++i) { HT[i].lchild=0; HT[i].rchild=0; HT[i].parent=0; HT[i].tag=1; HT[i].data='\0'; } //依次輸入待編碼的數據的權重 
    cout<<"請依次輸入每一個字和它的權重:"<<endl; for(int i=1;i<=n;++i) { scanf("%c",&HT[i].data); getchar(); scanf("%d",&HT[i].weight); getchar(); // cin>>HT[i].data>>HT[i].weight;
 } //構造 Huffman樹
    int s1,s2; for(int i=n+1;i<=m;++i) { Select(HT,i-1,s1,s2); //在已經有數據的哈夫曼節點中,選擇兩個雙親域為0,且權值最小的結點 //並返回它們在HT中的序號s1和s2
        HT[s1].parent=i; HT[s2].parent=i; //表示從F中刪除s1,s2
        HT[i].lchild=s1; HT[i].rchild=s2; //s1,s2分別作為i的左右孩子
        HT[i].weight=HT[s1].weight + HT[s2].weight; //i 的權值為左右孩子權值之和
 } cout<<" 結點 | data | weight | lchild | rchild | parent "<<endl; for(int i=1;i<=m;++i) { cout<<i<<" | "<<HT[i].data<<" | "<<HT[i].weight<<" | "<<HT[i].lchild<<" | "<<HT[i].rchild<<" | "<<HT[i].parent<<endl; } } //根據創建的哈夫曼樹,從葉子到根逆向求每個字符的赫夫曼編碼,存儲在編碼表HC中
void CreatHuffmanCode(HuffmanTree HT, HuffmanCode &HC, int n) { /*n:代表編碼個數*/ HC.code=new string[n+1];                 //分配n個指向字符串的指針
    HC.data=new char[n+1]; HC.num=n+1;//從1開始存 
     
    for(int i=1; i<=n; ++i) { //逐個字符求赫夫曼編碼
        int c=i; //哈夫曼表的下標
        int f=HT[i].parent; string cd=""; while(f!=0) { //從葉子結點開始向上回溯,直到根結點
             if (HT[f].lchild==c) { cd+="0";    //結點c是f的左孩子,則生成代碼0
 } else { cd+="1"; //結點c是f的右孩子,則生成代碼1
 } c=f; //跟新孩子,找上一代
             f=HT[f].parent;                     //繼續向上回溯
 } reverse(cd.begin(),cd.end()); HC.code[i]=cd;   //將求得的編碼從臨時空間cd復制到HC的當前行中 // cout<<cd<<endl; 
 } cout<<"當前的哈夫曼編碼表為:"<<endl; for(int i=1;i<=n;++i) { HC.data[i]=HT[i].data; cout<<i<<" | "<<HC.data[i]<<" | "<<HC.code[i]<<endl; } } void Encoding(HuffmanCode HC,string str) { cout<<"編碼結果為:"<<endl; for(int i=0;i<str.length();++i) { for(int j=1;j<=HC.num;++j) { // cout<<"\nHC.data[j]==str[i]"<<HC.data[j]<<" "<<str[i]<<endl; 
            if(HC.data[j]==str[i]) { cout<<HC.code[j]; break; } } } } void Decoding(HuffmanCode HC,string str) { cout<<"解碼結果為:"<<endl; string temp=""; int postion=0; for(int i=0;i<str.length();) { for(int j=1;j<=HC.num;++j) { int k=0; // cout<<"\n當前查找的是:"<<HC.code[j]; 
            for(;k<HC.code[j].length();++k) { // cout<<" HC.code[j][k]!=str[i] "<<HC.code[j][k]<<","<<str[i+k]; 
                if(HC.code[j][k]!=str[i+k]) { break; } } // cout<<" k="<<k<<endl;
            if(k==HC.code[j].length()) { i+=HC.code[j].length(); cout<<HC.data[j]; break; } } } } int main() { HuffmanTree HT; HuffmanCode HC; //構造赫夫曼樹,輸出各字符的赫夫曼編碼
    cout<<"\n請輸入編碼的個數:"<<endl; int n=0; cin>>n; getchar(); CreatHuffmanTree(HT,n); CreatHuffmanCode(HT,HC,n); // 編碼:輸入字符序列,輸出對應的赫碼序列。
    cout<<"\n請輸入要編碼的字符:"<<endl; string e_str=""; getline(cin,e_str); Encoding(HC,e_str); // cout<<e_str<<endl; // 譯碼:輸入赫夫曼碼序列,輸出原始字符代碼。
    cout<<"\n請輸入要解碼的字符:"<<endl; string d_str=""; getline(cin,d_str); Decoding(HC,d_str); }
View Code

未加注釋清爽版:

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string>
 4 #include<cstring>
 5 #include<algorithm>
 6 #define MAX 0x3f3f3f3f 
 7 using namespace std;  8 
 9 typedef struct
 10 {  11     char data;  12     int weight;  13     int parent;  14     int lchild;  15     int rchild;  16     bool tag;  17 }Huffnode,*HuffmanTree;  18 typedef struct
 19 {  20     string *code;  21     char *data;  22     int num;  23 }HuffmanCode;  24 void DisplayHuffmanCode(HuffmanCode &HC,int n)  25 {  26     for(int i=0;i<n;++i)  27  {  28         cout<<HC.code[i]<<endl;  29  }  30 }  31 void Select(HuffmanTree &HT,int index, int &s1, int &s2)  32 {  33     int min1=MAX;  34     int min2=MAX;  35     for(int i=1;i<=index;++i)  36  {  37         if(HT[i].parent==0&&HT[i].tag)  38  {  39             if(HT[i].weight<min1)  40  {  41                 s1=i;  42                 min1=HT[i].weight;  43  }  44  }  45  }  46     HT[s1].tag=0;  47     for(int i=1;i<=index;++i)  48  {  49         if(HT[i].parent==0&&HT[i].tag)  50  {  51             if(HT[i].weight<min2)  52  {  53                 s2=i;  54                 min2=HT[i].weight;  55  }  56  }  57  }  58     HT[s2].tag=0;  59 }  60 void CreatHuffmanTree(HuffmanTree &HT,int n)  61 {  62     if(n<=1)return;  63     int m=2*n-1;  64     HT=new Huffnode[m+1];  65 
 66     for(int i=1;i<=m;++i)  67  {  68         HT[i].lchild=0;  69         HT[i].rchild=0;  70         HT[i].parent=0;  71         HT[i].tag=1;  72         HT[i].data='\0';  73  }  74     cout<<"請依次輸入每一個字和它的權重:"<<endl;  75     for(int i=1;i<=n;++i)  76  {  77         scanf("%c",&HT[i].data);  78  getchar();  79         scanf("%d",&HT[i].weight);  80  getchar();  81  }  82 
 83     int s1,s2;  84     for(int i=n+1;i<=m;++i)  85  {  86         Select(HT,i-1,s1,s2);  87         HT[s1].parent=i;  88         HT[s2].parent=i;  89         HT[i].lchild=s1;  90         HT[i].rchild=s2;  91         HT[i].weight=HT[s1].weight + HT[s2].weight;  92  }  93 }  94 void CreatHuffmanCode(HuffmanTree HT, HuffmanCode &HC, int n)  95 {  96 
 97     HC.code=new string[n+1];  98     HC.data=new char[n+1];  99     HC.num=n+1; 100      
101     for(int i=1; i<=n; ++i) 102  { 103         int c=i; 104         int f=HT[i].parent; 105         string cd=""; 106         while(f!=0) 107  { 108              if (HT[f].lchild==c) 109  { 110                  cd+="0"; 111  } 112              else 
113  { 114                  cd+="1"; 115  } 116              c=f; 117              f=HT[f].parent; 118  } 119  reverse(cd.begin(),cd.end()); 120         HC.code[i]=cd; 121  } 122       cout<<"當前的哈夫曼編碼表為:"<<endl; 123       for(int i=1;i<=n;++i) 124  { 125           HC.data[i]=HT[i].data; 126           cout<<i<<" | "<<HC.data[i]<<" | "<<HC.code[i]<<endl; 127           
128  } 129 } 130 void Encoding(HuffmanCode HC,string str) 131 { 132     cout<<"編碼結果為:"<<endl; 133     for(int i=0;i<str.length();++i) 134  { 135         for(int j=1;j<=HC.num;++j) 136  { 137             if(HC.data[j]==str[i]) 138  { 139                 cout<<HC.code[j]; 140                 break; 141  } 142  } 143         
144  } 145 } 146 void Decoding(HuffmanCode HC,string str) 147 { 148     cout<<"解碼結果為:"<<endl; 149     string temp=""; 150     int postion=0; 151     for(int i=0;i<str.length();) 152  { 153         for(int j=1;j<=HC.num;++j) 154  { 155             int k=0; 156             for(;k<HC.code[j].length();++k) 157  { 158                 if(HC.code[j][k]!=str[i+k]) 159  { 160                     break; 161  } 162  } 163             if(k==HC.code[j].length()) 164  { 165                 i+=HC.code[j].length(); 166                 cout<<HC.data[j]; 167                 break; 168  } 169  } 170  } 171 } 172 int main() 173 { 174  HuffmanTree HT; 175  HuffmanCode HC; 176     //構造赫夫曼樹,輸出各字符的赫夫曼編碼
177     cout<<"\n請輸入編碼的個數:"<<endl; 178     int n=0; 179     cin>>n; 180  getchar(); 181  CreatHuffmanTree(HT,n); 182  CreatHuffmanCode(HT,HC,n); 183     // 編碼:輸入字符序列,輸出對應的赫碼序列。
184     cout<<"\n請輸入要編碼的字符:"<<endl; 185     string e_str=""; 186  getline(cin,e_str); 187  Encoding(HC,e_str); 188     // 譯碼:輸入赫夫曼碼序列,輸出原始字符代碼。
189     cout<<"\n請輸入要解碼的字符:"<<endl; 190     string d_str=""; 191  getline(cin,d_str); 192  Decoding(HC,d_str); 193      
194 }

測試樣例:

輸入:

27

輸入:

 
186 a 64 b 13 c 22 d 32 e 103 f 21 g 15 h 47 i 57 j 1 k 5 l 32 m 20 n 56 o 63 P 15 q 1 r 48 s 51 t 80 u 23 v 8 w 18 x 1 y 16 z 1
View Code

輸入:

you are bad gay but laolao is not

輸入:

1000111001000011111010001001011110000010101011011110000110101000111111000000000111011111011110101001101111010100111101110011111011010011101

輸出:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM