第六周作业——1.利用哈夫曼编码英文字母表,2哈夫曼编码实现

题目一:

(1)最优huffman编码为:

  111 (此字符为空格)
a 1010
b 100100
c 00101
d 10111
e 010
f 110100
g 100111
h 0001
i 0111
j 1101101110
k 11011010
l 10110
m 110111
n 0110
o 1000
p 100110
q 1101101100
r 0000
s 0011
t 1100
u 00100
v 1101100
w 110101
x 1101101111
y 100101
z 1101101101

(2)平均编码长度为5.74074;

(3)认为嫡值会比平均编码长度小.因为嫡值包含有概率的计算,算出来的压缩比会更高,即编码长度会较小.

(4)感觉除了标点外.英文压缩或许就字母频率了.


2哈夫曼编码实现

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include <iostream>  
  2. #include <fstream>  
  3. #include <queue>  
  4. #include <string>  
  5. #include <algorithm>  
  6. using namespace std;  
  7.   
  8. class Node  
  9. {  
  10. public:  
  11.     char mchar;  
  12.     int mweight;  
  13.     Node *lchild,*rchild;  
  14.   
  15.     Node()  
  16.     {  
  17.         mchar='!';      //不是叶子结点就叹号表示  
  18.         lchild=rchild=NULL;  
  19.     }  
  20.     Node(char c,int w)  
  21.     {  
  22.         mchar=c;  
  23.         mweight=w;  
  24.         lchild=rchild=NULL;  
  25.     }  
  26.     //Node(Node &n)  
  27.     //{  
  28.     //  mchar=n.mchar;  
  29.     //  mweight=n.mweight;  
  30.     //  lchild=n.lchild;  
  31.     //  rchild=n.rchild;  
  32.     //}  
  33. };  
  34. bool operator <(Node a,Node b)  
  35. {  
  36.     return a.mweight>b.mweight;  
  37. }  
  38.   
  39. class HuffmanTree  
  40. {  
  41. public:  
  42.     long mbitlenlastcoding;  
  43.     int mSumBitLen;  
  44.     Node *root;  
  45.     //queue头中自带有优先队列.如此定义可以小的先出队.注意要如此重载<运算符  
  46.     priority_queue<Node> H;  
  47.     vector<Node*> V;  
  48.     vector<string> CodeTable;  
  49.   
  50.     HuffmanTree()  
  51.     {  
  52.         mbitlenlastcoding=0;  
  53.         mSumBitLen=0;  
  54.         root=NULL;  
  55.     }  
  56.   
  57.   
  58.     void CreateTree(int *farray,string chartable,int num)  
  59.     {  
  60.         SetQueueH(farray,chartable,num);  
  61.         for(int k=0;k<num-1;k++)     //智能指针可能可以自动销毁  
  62.         {  
  63.             Node *i=new Node(H.top());  
  64.             //auto_ptr<Node> api(i);  
  65.             H.pop();  
  66.             Node *j=new Node(H.top());  
  67.             //auto_ptr<Node> apj(j);  
  68.             H.pop();  
  69.   
  70.             Node *fk=new Node;  
  71.             //auto_ptr<Node> apfk(fk);  
  72.             fk->lchild=i;  
  73.             fk->rchild=j;  
  74.             fk->mweight=i->mweight + j->mweight;  
  75.   
  76.             H.push(*fk);  
  77.             root=fk;        //运算到第n-1次时.FK就是root  
  78.         }  
  79.         LinearizeTree();                                //线性存储huffman树  
  80.         string str(" ");  
  81.         CreateCodeTable(root,str,-1);                   //创建编码表  
  82.         sort(CodeTable.begin(),CodeTable.end());        //对编码表按字母序排序.方便压缩时查找  
  83.     }  
  84.   
  85.     void Coding(const char* str)    //编码  
  86.     {  
  87.         ofstream fout;  
  88.         fout.open("text.dat",ios::binary);  
  89.         int bit=0;  
  90.         int bitcount=0;  
  91.         for(int i=0;i<strlen(str);i++)  
  92.         {  
  93.             int j=0;  
  94.             if(str[i]>='A' && str[i]<='Z')  
  95.                 j=str[i]-'A'+1;  
  96.             else if(str[i]>='a' && str[i]<='z')  
  97.                 j=str[i]-'a'+1;  
  98.             else if(' '==str[i])  
  99.                 j=0;  
  100.             string code(CodeTable[j].substr(2));  
  101.             mbitlenlastcoding+=code.length(); //保存实际编码的位数,供解压缩使用;  
  102.             for(int k=0;k<code.length();k++)  
  103.             {  
  104.                 if('0'==code.at(k))         //按序把编码放到高位.也可以放到低位  
  105.                     bit=bit<<1;  
  106.                 else  
  107.                     bit=(bit<<1)+1;           // 放低位,此步改为与0x80000000相或,bit=(bit|0x80000000);  
  108.                 bitcount=(bitcount+1)%32;  
  109.                 if(0==bitcount)  
  110.                     fout.write((char*)&bit,sizeof(bit));  
  111.             }  
  112.         }  
  113.         if(0!=bitcount)         //将最后不满32位的位移动到最高位  
  114.         {  
  115.             bitcount=32-bitcount;  
  116.             bit=bit<<bitcount;  
  117.             fout.write((char*)&bit,sizeof(bit));  
  118.         }  
  119.         fout.close();  
  120.     }  
  121.   
  122.     void Decodeing(char *infilename,char *outfilename)              //解码  
  123.     {  
  124.         ifstream fin;  
  125.         fin.open(infilename,ios::binary);  
  126.         if(true==fin.fail())   
  127.         {  
  128.             cerr<<"file read fail"<<endl;  
  129.             return;  
  130.         }  
  131.   
  132.         bool overflag=false;  
  133.         long bitcount=0;  
  134.         int buffsize=sizeof(int)*8;  
  135.         char buff[sizeof(int)*8+1];     //+1用来保存串结束符  
  136.         int bit;  
  137.         Node *p=root;  
  138.         string strResult;  
  139.         while(!overflag)  
  140.         {  
  141.             fin.read((char*)&bit,sizeof(bit));  
  142.             mbitlenlastcoding=mbitlenlastcoding-buffsize;  
  143.             _itoa(bit,buff,2);  
  144.             //因为_itoa函数转换二进制数时.若前几位为零时,不会转换位零,要自行添加  
  145.             string str(buff);  
  146.             str.insert(0,buffsize-strlen(buff),'0');  
  147.             if(mbitlenlastcoding<0)  
  148.             {  
  149.                 mbitlenlastcoding=buffsize+mbitlenlastcoding;  
  150.                 str=str.substr(0,mbitlenlastcoding);  
  151.                 buffsize=str.length();  
  152.                 overflag=true;      //置结束标志  
  153.             }  
  154.             int i=0;  
  155.             while(i<buffsize )  
  156.             {  
  157.                 if('!' !=p->mchar)  
  158.                 {  
  159.                     strResult.push_back(p->mchar);  
  160.                     p=root;  
  161.                 }  
  162.                 else  
  163.                 {  
  164.                     if('0'==str.at(i++))  
  165.                         p=p->lchild;  
  166.                     else  
  167.                         p=p->rchild;  
  168.                 }  
  169.             }  
  170.         }  
  171. //      cout<<strResult<<endl;  
  172.         ofstream fout(outfilename);  
  173.         fout<<strResult;  
  174.         fout.close();  
  175.         fin.close();  
  176.     }  
  177.   
  178.     void ShowQueueH()  
  179.     {  
  180.         while(!H.empty())  
  181.         {  
  182.             Node t=H.top();  
  183.             H.pop();  
  184.             cout<<t.mchar<<" "<<t.mweight<<endl;  
  185.         }  
  186.     }  
  187.   
  188.     void ShowTree()  
  189.     {  
  190.         for(int i=0;i<V.size();i++)  
  191.             cout<<i<<" "<<V[i]->mchar<<" "<<V[i]->mweight<<endl;  
  192.     }  
  193.   
  194.     void ShowCodeTable()  
  195.     {  
  196.         for(int i=0;i<CodeTable.size();i++)  
  197.             cout<<CodeTable.at(i)<<endl;  
  198.     }  
  199.   
  200.     void PrintCodeTable(char *filename)  
  201.     {  
  202.         ofstream fout(filename);  
  203.         for(int i=0;i<CodeTable.size();i++)  
  204.             fout<<CodeTable[i]<<endl;  
  205.         fout.close();  
  206.     }  
  207.   
  208.     ~HuffmanTree()  
  209.     {  
  210.         for(int i=0;i<V.size();i++)  
  211.         {  
  212.             if(NULL!=V[i])  
  213.                 delete V[i];  
  214.         }  
  215.     }  
  216. private:  
  217.     void SetQueueH(int *farray,string chartable,int num)  
  218.     {  
  219.         for(int i=0;i<num;i++)  
  220.         {  
  221.             Node t(chartable.at(i),farray[i]);  
  222.             H.push(t);  
  223.         }  
  224.     }  
  225.   
  226.     void LinearizeTree()                //线性存储huffman树  
  227.     {  
  228.         queue<Node> S;  
  229.         S.push(*root);  
  230.         V.push_back(root);  
  231.         while(!S.empty())  
  232.         {  
  233.             Node t=S.front();  
  234.             S.pop();  
  235.             if(NULL != t.lchild)  
  236.             {  
  237.                 S.push( (*t.lchild) );  
  238.                 V.push_back(t.lchild);        
  239.             }  
  240.             if(NULL != t.rchild)  
  241.             {  
  242.                 S.push( (*t.rchild) );  
  243.                 V.push_back(t.rchild);  
  244.             }  
  245.         }  
  246.     }  
  247.   
  248.     void CreateCodeTable(Node *p,string str,int flag)  
  249.     {  
  250.         if (NULL == p ) return ;  
  251.         if(0==flag) str.push_back('0');//str.append("0");  
  252.         else if(1==flag) str.push_back('1');//str.append("1");  
  253.         if('!' != p->mchar)  
  254.         {  
  255.             mSumBitLen+=(str.length()-1);       //加上编码的长度  
  256.             str.insert(str.begin(),p->mchar);  
  257.             CodeTable.push_back(str);  
  258.             return;  
  259.         }  
  260.         else  
  261.         {  
  262.             if(NULL!=p->lchild)  
  263.                 CreateCodeTable(p->lchild,str,0);  
  264.             if(NULL!=p->rchild)  
  265.                 CreateCodeTable(p->rchild,str,1);  
  266.         }  
  267.     }  
  268. };  
  269.   
  270. void main()  
  271. {  
  272.     string chartable(" etaoinshrdlcumwfgypbvkjxqz");  
  273.     int farray[]={183,102,77,68,59,58,55,51,49,48,35,34,26,24,21,19,18,17,16,16,13,9,6,2,2,1,1};  
  274.     char text[]="Chapter Graphs surveys the most important graph processing problems  including depth first search breadth first search minimum spanning trees and shortest paths ";  
  275.   
  276.     HuffmanTree ht;  
  277.     ht.CreateTree(farray,chartable,chartable.length());  
  278.     ht.ShowTree();  
  279.     ht.ShowCodeTable();  
  280.     ht.PrintCodeTable("CodeTable.txt");  
  281.     ht.Coding(text);  
  282.     ht.Decodeing("text.dat","Decoding.txt");  
  283.     cout<<"平均编码长度:"<<ht.mSumBitLen/27.0<<endl;  
  284. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值