之前看到cppblog一篇关于huffman的文,和我今早的一个梦不谋而合。我记得似乎曾经给前女友写过一个Huffman的课程大作业,花了当天晚上的一些时间,只是为了完成任务而写的,草草的回忆了一下huffman的原理,然后就开始写了,当时因为她的作业并没要求规模,我只把控制台输入端作为文件输入,先压缩再解压,并且把所有中间过程输出。
我知道自己有个弱点,当自己不把模块划分得很细,那么DEBUG的时间就会变得相对长一些,但是那一次写哈夫曼编码就完全是认为这种作业就不必划分得太细也能很容易实现。结果今早由于梦见一个诡异的梦(梦见自己得了绝症,她那弱不禁风的身影在梦里不断浮现...),又看到有人写了篇哈夫曼编码的随笔,我就重新打开那个我写的工程运行了一次。
嗯,运行正确,然后我找来一篇英文小说复制了一大片进去,结果bug出现了。接着是我不断找bug的过程(比如当时规模设置得太小,只是为了给她应付作业;再比如bit位批量处理类型等等细节...)
在搞定两个bug,最终还有一个诡异的bug没解决,I give up. 我知道这个错误之所以难以找到,是因为自己为了随意发挥违背自己历来遵从的编程原则,就算找到那个bug也无济于事,不如以后不再任性,把模块按down-top、top-down划分(这种方法几乎能让我不出任何错),并且写代码的时候,为每一次项目的测试单元和调试代码做准备。
当时自己任性写的代码如下(注释是很全面,因为当时要给她去交作业,但是却发现那些注释只是给她老师看的,而非给我自己看的....因为我没有在注释里面详细定义哈夫曼编码压缩后的压缩文件格式信息):
(以下代码的input不能直接处理Unicode,写成重定向到文件可以)
嗯嗯,我还把自己这段代码复制到百度知道回答别人的问题过~~真是贻害四方瓦。
执行的case如下:
写到此处,我突然发现在进行位处理的时候,我并没有用一个更简化的方法(100行内可以解决)- -bnr ,好吧 下次写一个通用的压缩软件。
我知道自己有个弱点,当自己不把模块划分得很细,那么DEBUG的时间就会变得相对长一些,但是那一次写哈夫曼编码就完全是认为这种作业就不必划分得太细也能很容易实现。结果今早由于梦见一个诡异的梦(梦见自己得了绝症,她那弱不禁风的身影在梦里不断浮现...),又看到有人写了篇哈夫曼编码的随笔,我就重新打开那个我写的工程运行了一次。
嗯,运行正确,然后我找来一篇英文小说复制了一大片进去,结果bug出现了。接着是我不断找bug的过程(比如当时规模设置得太小,只是为了给她应付作业;再比如bit位批量处理类型等等细节...)
在搞定两个bug,最终还有一个诡异的bug没解决,I give up. 我知道这个错误之所以难以找到,是因为自己为了随意发挥违背自己历来遵从的编程原则,就算找到那个bug也无济于事,不如以后不再任性,把模块按down-top、top-down划分(这种方法几乎能让我不出任何错),并且写代码的时候,为每一次项目的测试单元和调试代码做准备。
当时自己任性写的代码如下(注释是很全面,因为当时要给她去交作业,但是却发现那些注释只是给她老师看的,而非给我自己看的....因为我没有在注释里面详细定义哈夫曼编码压缩后的压缩文件格式信息):
(以下代码的input不能直接处理Unicode,写成重定向到文件可以)
嗯嗯,我还把自己这段代码复制到百度知道回答别人的问题过~~真是贻害四方瓦。
1
#include
<
iostream
>
2
3 using namespace std;
4
5 #define MAX_FILE 50000 // 假设的文件最大长度
6 #define MAXLIST 256 // 最大MAP值
7 #define MAX_HUFFMAN_LENGTH 100 // 哈夫曼编码长度
8 unsigned char dictionary[MAXLIST][ 2 ] = {0} ; // Hash映射,[][0]为权值,[][1]为字符
9 unsigned char fileContent[MAX_FILE]; // 处理的字符串大小
10 int Huffman[MAXLIST][MAX_HUFFMAN_LENGTH] = {2} ; // 哈夫曼编码序列
11 unsigned char HuffmanList[MAXLIST] = {0} ; // 哈夫曼编码对应的字符有序序列
12 unsigned char HuffFileCode[MAX_FILE] = {0} ; // 哈夫曼编码字符串序列
13 unsigned char HuffFile[MAX_FILE] = {0} ;
14 // 编码到假设的文件的哈夫曼压缩格式: 依次存储 原字符串长度(1字节存储:可扩展到2字节)、哈夫曼编码数(1字节)、每个哈夫曼编码的长度序列、每个哈夫曼编码对应的字符序列、编码过的哈夫曼字符串
15
16 unsigned char GetFile[MAX_FILE] = {0} ; // 解码序列
17
18 void ShellSort(unsigned char pData[MAXLIST][ 2 ], int Count) // Shell排序,用于准备有序化要构造的编码权值构造哈夫曼树做准备
19 {
20 int step[4]={9,5,3,1};//增量序列
21
22 int iTemp,cTemp;
23 int k,s,w;
24 for(int i=0;i<4;i++)
25 {
26 k=step[i];
27 s=-k;
28 for(int j=k;j<Count;j++)
29 {iTemp=pData[j][0];
30 cTemp=pData[j][1];
31 w=j-k;
32 if(s==0)
33 {
34 s=-k;
35 s++;
36 pData[s][0]=iTemp;
37 pData[s][1]=cTemp;
38 }
39 while((iTemp<pData[w][0])&&(w>=0)&&(w<=Count))
40 {
41 pData[w+k][0]=pData[w][0];//权值交换
42 pData[w+k][1]=pData[w][1];//字符交换
43 w=w-k;
44 }
45 pData[w+k][0]=iTemp;
46 pData[w+k][1]=cTemp;
47 }
48 }
49}
50
51
52 struct TNode // 哈夫曼树结点
53 {
54 TNode* pNode;
55 TNode* lNode;
56 TNode* rNode;
57 unsigned char dictionary;
58 unsigned char weight;
59 TNode(unsigned char dic,unsigned char wei)
60 {
61 pNode=0;
62 lNode=0;
63 rNode=0;
64 dictionary=dic;
65 weight=wei;
66 }
67} ;
68
69 struct LNode // 链表结点,用于存储哈夫曼树结点,进而构造哈夫曼树(保证每一步链表结点包含的哈夫曼结点都是有序的)
70 {
71 LNode* prev;
72 LNode* next;
73 TNode* tnode;
74 LNode()
75 {
76 prev=next=0;
77 tnode=0;
78 }
79} ;
80
81 int len = 0 ; // 哈夫曼编码数
82 int deep =- 1 ; // 深度
83 void Preorder(TNode * p); // 前序遍历
84 void byLeft(TNode * p) // 经由左结点
85 {
86 deep++;
87 Huffman[len][deep]=0;
88 Preorder(p);
89
90 Huffman[len][deep]=2;
91 deep--;
92}
93 void byRight(TNode * p) // 经由右结点
94 {
95
96 deep++;
97 Huffman[len][deep]=1;
98 Preorder(p);
99
100 Huffman[len][deep]=2;
101 deep--;
102}
103 void Preorder(TNode * p)
104 {
105
106 if(p->lNode!=0)//当左子结点非空则遍历
107 {
108
109 byLeft(p->lNode);
110 }
111 if(p->rNode!=0)//当右子结点非空则遍历
112 {
113 byRight(p->rNode);
114 }
115
116
117
118 if((p->lNode==0)&&(p->rNode==0))//当左右结点都为空,则增加哈夫曼编码数到另一个记录
119 {
120
121 Huffman[len][deep+1]=2;
122 int i=0;
123 for(;Huffman[len][i]!=2;i++)
124 {
125 Huffman[len+1][i]=Huffman[len][i];
126 }
127 Huffman[len+1][i]=2;
128
129 HuffmanList[len]=p->dictionary;
130
131
132
133 len++;
134 }
135
136}
137
138
139 unsigned char generateOne( int k) // 产生k个连续1的二进制串,比如111,1111,111111,用于编码进假设的文件
140 {
141 unsigned char c=0;
142 for(;k!=0;k--)
143 {
144 c|=(1<<(k-1));
145
146 }
147 return c;
148}
149
150 int compareBits(unsigned char b1,unsigned char b2,unsigned char c, int l, int d) // 判断由 [b1,b2] 组成的16位二进制数以d为起点,是否是长度为l的c二进制串(哈夫曼编码)的前缀
151 {
152 unsigned __int8 t=(((((0x00ff&b1)<<8)|(0x00ff&b2))>>(8-d))&0x00ff);
153 return (((t)&((generateOne(l)<<(8-l))&0xff))==((c<<(8-l))&0xff));
154}
155 void input(unsigned char * _list,unsigned char end)
156 {
157
158 int i=0;
159 for(;(_list[i]=cin.get())!=end;i++);
160 _list[i]='\0';
161
162}
163
164 int main()
165 {
166
167 /**//* 或许假定的文件字符串向量中的字符串 */
168 cout<<"请输入要压缩的字符串:";
169 input(fileContent,'$');
170
171 unsigned int fileLen=0;
172
173
174 /**//* Hash进dictionary */
175 for(int i=0;fileContent[i]!='\0';i++,fileLen++)
176 {
177
178 ++dictionary[fileContent[i]][0];
179 dictionary[fileContent[i]][1]=fileContent[i];
180 }
181 unsigned int len=0;
182
183 /**//* 把Hash了的dictionary向前靠拢 */
184
185
186 {
187 for(int i=0;i!=MAXLIST;i++)
188 {
189
190 if(dictionary[i][0]!=0)
191 {
192 dictionary[len][0]=dictionary[i][0];
193 dictionary[len][1]=dictionary[i][1];
194 len++;
195 }
196 }
197 }
198 cout<<"哈夫曼编码个数:"<<len<<endl;
199 /**//* 对dictionary按权值进行排序 */
200
201 ShellSort(dictionary,len);
202
203 /**//* 构造链表,链表中放有序dictionary权值的树结点 */
204 LNode* head=new LNode,*p=head;
205 head->next=new LNode;
206 TNode *tempTNode=new TNode(dictionary[0][1],dictionary[0][0]);
207 head->tnode=tempTNode;
208
209
210 {
211 for(int i=0;i!=len-1;i++)
212 {
213 p->next->prev=p->next;
214 p=p->next;
215
216 p->next=new LNode;
217 tempTNode=new TNode(dictionary[i+1][1],dictionary[i+1][0]);
218 p->tnode=tempTNode;
219 }
220 }
221 delete p->next;
222 p->next=0;
223
224 /**//* 每次最小权值的前面两个链表结点中的树结点组成一个子树,子树有合权值,子数的根按权值排序进链表*/
225
226 for(p=head;p->next!=0;)
227 {
228
229 p->tnode->pNode=new TNode('\0',(p->tnode->weight)+(p->next->tnode->weight));
230 p->next->tnode->pNode=p->tnode->pNode;
231 p->tnode->pNode->lNode=p->tnode;
232 p->tnode->pNode->rNode=p->next->tnode;
233 head=p->next;
234 delete p;
235 p=head;
236 p->tnode=p->tnode->pNode;
237 for(LNode* t=head;t->next!=0;t=t->next)
238 {
239 if(t->tnode->weight>t->next->tnode->weight)
240 {
241 TNode* k=t->tnode;
242 t->tnode=t->next->tnode;
243 t->next->tnode=k;
244 }
245 }
246
247 }
248
249
250 int code[MAX_FILE],h=0;
251
252
253
254 /**//* 前序遍历构造哈夫曼编码 */
255 Preorder(p->tnode);
256
257 {
258 for(int i=0;i!=len;i++)
259 dictionary[HuffmanList[i]][0]=i;
260 }
261
262 int codeLen=0,total=0;
263 {
264
265 for(int i=0;i!=fileLen;i++)
266 {
267
268 unsigned int j=dictionary[fileContent[i]][0];
269
270
271 for(int k=0;Huffman[j][k]!=2;k++)
272 {
273
274 HuffFileCode[codeLen]|=(Huffman[j][k]<<(7-total%8));
275
276 code[h++]=Huffman[j][k];
277
278 if(((total+1)%8)==0)
279 {
280
281 HuffFile[4+len*3+2+codeLen]=HuffFileCode[codeLen];
282 codeLen++;
283 }
284 total++;
285 }
286
287
288
289 }
290 }
291
292 HuffFile[4+len*3+2+codeLen]=HuffFileCode[codeLen];
293
294
295 HuffFile[0]=((fileLen>>24));
296 HuffFile[1]=((fileLen>>16));
297 HuffFile[2]=((fileLen>>8));
298 HuffFile[3]=((fileLen));
299
300
301
302 /**//* 解压缩假定的文件HuffFile成为原字符串序列 */
303 cout<<"哈夫曼编码序列:\n";
304
305 /**//* 哈夫曼编码表长度 */
306 HuffFile[4]=(len&0xff00)>>8;
307 HuffFile[5]=len&0x00ff;
308
309
310
311 {
312 for(int i=0,j=0;i!=len;i++,j=0)
313 {
314
315 for(;Huffman[i][j]!=2;j++);
316
317 HuffFile[3+i+2+1]=j;
318 HuffFile[3+i+2+2*len+1]=HuffmanList[i];
319
320
321 for(int k=0;k!=j;k++)
322 {
323
324 cout<<Huffman[i][k];
325 HuffFile[3+i+2+len+1]|=(Huffman[i][k]<<(j-1-k));
326
327 }
328 cout<<":"<<HuffmanList[i]<<endl;
329
330
331 }
332 }
333
334
335
336 unsigned int packFileLen=(HuffFile[0]<<24)|(HuffFile[1]<<16)|(HuffFile[2]<<8)|(HuffFile[3]<<0);
337 unsigned int packCodeLen=((unsigned int)HuffFile[4]<<8)|((unsigned int)HuffFile[5]);
338
339
340 {
341 for(int i=0,j=0;i!=(packFileLen);i++)
342 {
343 for(int k=0;k!=packCodeLen;k++)
344 {
345
346 unsigned char l=HuffFile[3+2+k+1],d=j%8,b1=HuffFile[3+j/8+2+packCodeLen*3+1],b2=HuffFile[3+j/8+1+2+packCodeLen*3+1];
347
348 unsigned char c=HuffFile[3+packCodeLen+2+k+1];
349
350 if(compareBits(b1,b2,c,l,d))
351 {
352
353 j+=HuffFile[3+2+k+1];
354
355 GetFile[i]=HuffFile[3+2+packCodeLen*2+k+1];
356 cout<<GetFile[i];
357
358 break;
359
360 }
361 }
362
363 }
364 }
365
366 {
367 cout<<"哈夫曼压缩后二进制序列:"<<endl;
368 for(int i=0;i!=h;i++)
369 {
370 cout<<code[i];
371 if((i+1)%8==0)
372 cout<<" ";
373 }
374 }
375 cout<<endl;
376
377 {
378 cout<<"哈夫曼压缩打包假定文件格式二进制的文本体现:";
379 cout<<endl;
380 for(int i=0;i!=packFileLen+packCodeLen*3;i++)
381 {
382 cout<<HuffFile[i];
383 }
384 cout<<endl;
385 }
386
387 cout<<"原字节数为:"<<fileLen<<endl;
388 cout<<"压缩后字节数为:"<<(h)/8+1<<endl;
389 cout<<"压缩率为"<<((h/8.0+1)/fileLen)*100<<"%"<<endl;
390
391
392 {
393
394 cout<<"字符串字节数为:"<<(packFileLen)<<endl;
395 cout<<"字符串解压序列为:";
396 unsigned char buffer[MAX_FILE];
397 int i;
398 for(i=0;i!=(packFileLen);i++)
399 {
400 buffer[i]=GetFile[i];
401 }
402 buffer[i]=0;
403 cout<<buffer<<endl;
404
405
406
407
408 cout<<endl;
409
410 }
411 return 1;
412}
2
3 using namespace std;
4
5 #define MAX_FILE 50000 // 假设的文件最大长度
6 #define MAXLIST 256 // 最大MAP值
7 #define MAX_HUFFMAN_LENGTH 100 // 哈夫曼编码长度
8 unsigned char dictionary[MAXLIST][ 2 ] = {0} ; // Hash映射,[][0]为权值,[][1]为字符
9 unsigned char fileContent[MAX_FILE]; // 处理的字符串大小
10 int Huffman[MAXLIST][MAX_HUFFMAN_LENGTH] = {2} ; // 哈夫曼编码序列
11 unsigned char HuffmanList[MAXLIST] = {0} ; // 哈夫曼编码对应的字符有序序列
12 unsigned char HuffFileCode[MAX_FILE] = {0} ; // 哈夫曼编码字符串序列
13 unsigned char HuffFile[MAX_FILE] = {0} ;
14 // 编码到假设的文件的哈夫曼压缩格式: 依次存储 原字符串长度(1字节存储:可扩展到2字节)、哈夫曼编码数(1字节)、每个哈夫曼编码的长度序列、每个哈夫曼编码对应的字符序列、编码过的哈夫曼字符串
15
16 unsigned char GetFile[MAX_FILE] = {0} ; // 解码序列
17
18 void ShellSort(unsigned char pData[MAXLIST][ 2 ], int Count) // Shell排序,用于准备有序化要构造的编码权值构造哈夫曼树做准备
19 {
20 int step[4]={9,5,3,1};//增量序列
21
22 int iTemp,cTemp;
23 int k,s,w;
24 for(int i=0;i<4;i++)
25 {
26 k=step[i];
27 s=-k;
28 for(int j=k;j<Count;j++)
29 {iTemp=pData[j][0];
30 cTemp=pData[j][1];
31 w=j-k;
32 if(s==0)
33 {
34 s=-k;
35 s++;
36 pData[s][0]=iTemp;
37 pData[s][1]=cTemp;
38 }
39 while((iTemp<pData[w][0])&&(w>=0)&&(w<=Count))
40 {
41 pData[w+k][0]=pData[w][0];//权值交换
42 pData[w+k][1]=pData[w][1];//字符交换
43 w=w-k;
44 }
45 pData[w+k][0]=iTemp;
46 pData[w+k][1]=cTemp;
47 }
48 }
49}
50
51
52 struct TNode // 哈夫曼树结点
53 {
54 TNode* pNode;
55 TNode* lNode;
56 TNode* rNode;
57 unsigned char dictionary;
58 unsigned char weight;
59 TNode(unsigned char dic,unsigned char wei)
60 {
61 pNode=0;
62 lNode=0;
63 rNode=0;
64 dictionary=dic;
65 weight=wei;
66 }
67} ;
68
69 struct LNode // 链表结点,用于存储哈夫曼树结点,进而构造哈夫曼树(保证每一步链表结点包含的哈夫曼结点都是有序的)
70 {
71 LNode* prev;
72 LNode* next;
73 TNode* tnode;
74 LNode()
75 {
76 prev=next=0;
77 tnode=0;
78 }
79} ;
80
81 int len = 0 ; // 哈夫曼编码数
82 int deep =- 1 ; // 深度
83 void Preorder(TNode * p); // 前序遍历
84 void byLeft(TNode * p) // 经由左结点
85 {
86 deep++;
87 Huffman[len][deep]=0;
88 Preorder(p);
89
90 Huffman[len][deep]=2;
91 deep--;
92}
93 void byRight(TNode * p) // 经由右结点
94 {
95
96 deep++;
97 Huffman[len][deep]=1;
98 Preorder(p);
99
100 Huffman[len][deep]=2;
101 deep--;
102}
103 void Preorder(TNode * p)
104 {
105
106 if(p->lNode!=0)//当左子结点非空则遍历
107 {
108
109 byLeft(p->lNode);
110 }
111 if(p->rNode!=0)//当右子结点非空则遍历
112 {
113 byRight(p->rNode);
114 }
115
116
117
118 if((p->lNode==0)&&(p->rNode==0))//当左右结点都为空,则增加哈夫曼编码数到另一个记录
119 {
120
121 Huffman[len][deep+1]=2;
122 int i=0;
123 for(;Huffman[len][i]!=2;i++)
124 {
125 Huffman[len+1][i]=Huffman[len][i];
126 }
127 Huffman[len+1][i]=2;
128
129 HuffmanList[len]=p->dictionary;
130
131
132
133 len++;
134 }
135
136}
137
138
139 unsigned char generateOne( int k) // 产生k个连续1的二进制串,比如111,1111,111111,用于编码进假设的文件
140 {
141 unsigned char c=0;
142 for(;k!=0;k--)
143 {
144 c|=(1<<(k-1));
145
146 }
147 return c;
148}
149
150 int compareBits(unsigned char b1,unsigned char b2,unsigned char c, int l, int d) // 判断由 [b1,b2] 组成的16位二进制数以d为起点,是否是长度为l的c二进制串(哈夫曼编码)的前缀
151 {
152 unsigned __int8 t=(((((0x00ff&b1)<<8)|(0x00ff&b2))>>(8-d))&0x00ff);
153 return (((t)&((generateOne(l)<<(8-l))&0xff))==((c<<(8-l))&0xff));
154}
155 void input(unsigned char * _list,unsigned char end)
156 {
157
158 int i=0;
159 for(;(_list[i]=cin.get())!=end;i++);
160 _list[i]='\0';
161
162}
163
164 int main()
165 {
166
167 /**//* 或许假定的文件字符串向量中的字符串 */
168 cout<<"请输入要压缩的字符串:";
169 input(fileContent,'$');
170
171 unsigned int fileLen=0;
172
173
174 /**//* Hash进dictionary */
175 for(int i=0;fileContent[i]!='\0';i++,fileLen++)
176 {
177
178 ++dictionary[fileContent[i]][0];
179 dictionary[fileContent[i]][1]=fileContent[i];
180 }
181 unsigned int len=0;
182
183 /**//* 把Hash了的dictionary向前靠拢 */
184
185
186 {
187 for(int i=0;i!=MAXLIST;i++)
188 {
189
190 if(dictionary[i][0]!=0)
191 {
192 dictionary[len][0]=dictionary[i][0];
193 dictionary[len][1]=dictionary[i][1];
194 len++;
195 }
196 }
197 }
198 cout<<"哈夫曼编码个数:"<<len<<endl;
199 /**//* 对dictionary按权值进行排序 */
200
201 ShellSort(dictionary,len);
202
203 /**//* 构造链表,链表中放有序dictionary权值的树结点 */
204 LNode* head=new LNode,*p=head;
205 head->next=new LNode;
206 TNode *tempTNode=new TNode(dictionary[0][1],dictionary[0][0]);
207 head->tnode=tempTNode;
208
209
210 {
211 for(int i=0;i!=len-1;i++)
212 {
213 p->next->prev=p->next;
214 p=p->next;
215
216 p->next=new LNode;
217 tempTNode=new TNode(dictionary[i+1][1],dictionary[i+1][0]);
218 p->tnode=tempTNode;
219 }
220 }
221 delete p->next;
222 p->next=0;
223
224 /**//* 每次最小权值的前面两个链表结点中的树结点组成一个子树,子树有合权值,子数的根按权值排序进链表*/
225
226 for(p=head;p->next!=0;)
227 {
228
229 p->tnode->pNode=new TNode('\0',(p->tnode->weight)+(p->next->tnode->weight));
230 p->next->tnode->pNode=p->tnode->pNode;
231 p->tnode->pNode->lNode=p->tnode;
232 p->tnode->pNode->rNode=p->next->tnode;
233 head=p->next;
234 delete p;
235 p=head;
236 p->tnode=p->tnode->pNode;
237 for(LNode* t=head;t->next!=0;t=t->next)
238 {
239 if(t->tnode->weight>t->next->tnode->weight)
240 {
241 TNode* k=t->tnode;
242 t->tnode=t->next->tnode;
243 t->next->tnode=k;
244 }
245 }
246
247 }
248
249
250 int code[MAX_FILE],h=0;
251
252
253
254 /**//* 前序遍历构造哈夫曼编码 */
255 Preorder(p->tnode);
256
257 {
258 for(int i=0;i!=len;i++)
259 dictionary[HuffmanList[i]][0]=i;
260 }
261
262 int codeLen=0,total=0;
263 {
264
265 for(int i=0;i!=fileLen;i++)
266 {
267
268 unsigned int j=dictionary[fileContent[i]][0];
269
270
271 for(int k=0;Huffman[j][k]!=2;k++)
272 {
273
274 HuffFileCode[codeLen]|=(Huffman[j][k]<<(7-total%8));
275
276 code[h++]=Huffman[j][k];
277
278 if(((total+1)%8)==0)
279 {
280
281 HuffFile[4+len*3+2+codeLen]=HuffFileCode[codeLen];
282 codeLen++;
283 }
284 total++;
285 }
286
287
288
289 }
290 }
291
292 HuffFile[4+len*3+2+codeLen]=HuffFileCode[codeLen];
293
294
295 HuffFile[0]=((fileLen>>24));
296 HuffFile[1]=((fileLen>>16));
297 HuffFile[2]=((fileLen>>8));
298 HuffFile[3]=((fileLen));
299
300
301
302 /**//* 解压缩假定的文件HuffFile成为原字符串序列 */
303 cout<<"哈夫曼编码序列:\n";
304
305 /**//* 哈夫曼编码表长度 */
306 HuffFile[4]=(len&0xff00)>>8;
307 HuffFile[5]=len&0x00ff;
308
309
310
311 {
312 for(int i=0,j=0;i!=len;i++,j=0)
313 {
314
315 for(;Huffman[i][j]!=2;j++);
316
317 HuffFile[3+i+2+1]=j;
318 HuffFile[3+i+2+2*len+1]=HuffmanList[i];
319
320
321 for(int k=0;k!=j;k++)
322 {
323
324 cout<<Huffman[i][k];
325 HuffFile[3+i+2+len+1]|=(Huffman[i][k]<<(j-1-k));
326
327 }
328 cout<<":"<<HuffmanList[i]<<endl;
329
330
331 }
332 }
333
334
335
336 unsigned int packFileLen=(HuffFile[0]<<24)|(HuffFile[1]<<16)|(HuffFile[2]<<8)|(HuffFile[3]<<0);
337 unsigned int packCodeLen=((unsigned int)HuffFile[4]<<8)|((unsigned int)HuffFile[5]);
338
339
340 {
341 for(int i=0,j=0;i!=(packFileLen);i++)
342 {
343 for(int k=0;k!=packCodeLen;k++)
344 {
345
346 unsigned char l=HuffFile[3+2+k+1],d=j%8,b1=HuffFile[3+j/8+2+packCodeLen*3+1],b2=HuffFile[3+j/8+1+2+packCodeLen*3+1];
347
348 unsigned char c=HuffFile[3+packCodeLen+2+k+1];
349
350 if(compareBits(b1,b2,c,l,d))
351 {
352
353 j+=HuffFile[3+2+k+1];
354
355 GetFile[i]=HuffFile[3+2+packCodeLen*2+k+1];
356 cout<<GetFile[i];
357
358 break;
359
360 }
361 }
362
363 }
364 }
365
366 {
367 cout<<"哈夫曼压缩后二进制序列:"<<endl;
368 for(int i=0;i!=h;i++)
369 {
370 cout<<code[i];
371 if((i+1)%8==0)
372 cout<<" ";
373 }
374 }
375 cout<<endl;
376
377 {
378 cout<<"哈夫曼压缩打包假定文件格式二进制的文本体现:";
379 cout<<endl;
380 for(int i=0;i!=packFileLen+packCodeLen*3;i++)
381 {
382 cout<<HuffFile[i];
383 }
384 cout<<endl;
385 }
386
387 cout<<"原字节数为:"<<fileLen<<endl;
388 cout<<"压缩后字节数为:"<<(h)/8+1<<endl;
389 cout<<"压缩率为"<<((h/8.0+1)/fileLen)*100<<"%"<<endl;
390
391
392 {
393
394 cout<<"字符串字节数为:"<<(packFileLen)<<endl;
395 cout<<"字符串解压序列为:";
396 unsigned char buffer[MAX_FILE];
397 int i;
398 for(i=0;i!=(packFileLen);i++)
399 {
400 buffer[i]=GetFile[i];
401 }
402 buffer[i]=0;
403 cout<<buffer<<endl;
404
405
406
407
408 cout<<endl;
409
410 }
411 return 1;
412}
执行的case如下:
1
请输入要压缩的字符串:I ask the indulgence of the children who may read
this
boo
2 k for dedicating it to a grown - up. I have a serious reason: he is the best frie
3 nd I have in the world. I have another reason: this grown - up understands everyth
4 ing
5 even books about children. I have a third reason: he lives in France where he is
6 hungry and cold. He needs cheering up.$
7 哈夫曼编码个数: 30
8 哈夫曼编码序列:
9 0000 :t
10 00010000 :F
11 00010001 :H
12 00010010 : < 回车 >
13 00010011 :m
14 000101 :b
15 00011 :u
16 0010 :s
17 0011 :o
18 0100 :i
19 0101 :a
20 011 :e
21 100000 :I
22 100001 :.
23 1000100 : -
24 1000101 ::
25 100011 :w
26 1001 :r
27 1010 :h
28 1011 :n
29 1100000 :f
30 1100001 :y
31 1100010 :k
32 1100011 :p
33 110010 :l
34 110011 :g
35 110100 :c
36 110101 :v
37 11011 :d
38 111 :
39 I ask the indulgence of the children who may read this book for dedicating it to
40 a grown - up. I have a serious reason: he is the best friend I have in the world
41 . I have another reason: this grown - up understands everything
42 even books about children. I have a third reason: he lives in France where he is
43 hungry and cold. He needs cheering up.哈夫曼压缩后二进制序列:
44 10000011 10101001 01100010 11100001 01001111 10100101 11101100 01111001 01100110
45 11101111 01000111 11001111 00000111 00001010 01111111 01001010 01001100 1011011
46 1 00101110 11111100 01110100 01111100 01001101 01110000 11111001 01101011 101111
47 10 00010100 10000101 11000101 00110011 11000101 11110000 00011100 11111101 10111
48 101 10100110 10001010 00001001 01111001 11110100 00001110 00000111 11010111 1110
49 0111 00100111 00011101 11000100 00011110 00111000 01111111 10000011 11010010 111
50 01010 11111010 11110010 01110010 10000110 00110010 11110010 11010100 10001110 11
51 100010 11111010 01111101 00001011 10000101 00111110 00101011 00100000 11111000 0
52 0100101 00011101 11101111 11000001 11101001 01110101 01111101 00101111 10000101
53 00111111 00011001 11001110 01011011 10000111 11000001 11101001 01110101 01111101
54 01101100 11000010 10011100 11111001 01101010 01000111 01110001 01111000 0101001
55 0 00010111 11001110 01001110 00111011 10001000 00111100 01111100 01110111 101101
56 11 00100100 00001011 01111011 00101110 11110101 01110011 10000100 00101001 00101
57 111 00110001 00100111 10101011 10111110 00101001 10011110 00100010 11101010 0010
58 1001 10001100 00111110 10010100 10011001 01101110 01011101 11000011 11100000 111
59 10100 10111010 10111110 10111100 00101001 00100111 01111110 01011010 10010001 11
60 011100 01011111 01001111 11100100 10011010 10110010 11101001 01111100 01000010 0
61 1010110 11110100 01111110 00111010 01110010 11111101 00111110 10000101 11101000
62 01110111 10011100 11100001 11101011 01111011 11111010 00011110 01011011 10000111
63 10001000 10111111 01101101 11101100 10111110 10010100 11011100 10100101 1110011
64 1 11000111 10001110 0001
65 哈夫曼压缩打包假定文件格式二进制的文本体现:
66
67
68
69 (此处代码被截断,无法copy到剪贴板)
70
71 原字节数为: 341
72 压缩后字节数为: 181
73 压缩率为53. 2258 %
74 字符串字节数为: 341
75 字符串解压序列为:I ask the indulgence of the children who may read this book for
76 dedicating it to a grown - up. I have a serious reason: he is the best friend I
77 have in the world. I have another reason: this grown - up understands everything
78 even books about children. I have a third reason: he lives in France where he is
79 hungry and cold. He needs cheering up.
80
2 k for dedicating it to a grown - up. I have a serious reason: he is the best frie
3 nd I have in the world. I have another reason: this grown - up understands everyth
4 ing
5 even books about children. I have a third reason: he lives in France where he is
6 hungry and cold. He needs cheering up.$
7 哈夫曼编码个数: 30
8 哈夫曼编码序列:
9 0000 :t
10 00010000 :F
11 00010001 :H
12 00010010 : < 回车 >
13 00010011 :m
14 000101 :b
15 00011 :u
16 0010 :s
17 0011 :o
18 0100 :i
19 0101 :a
20 011 :e
21 100000 :I
22 100001 :.
23 1000100 : -
24 1000101 ::
25 100011 :w
26 1001 :r
27 1010 :h
28 1011 :n
29 1100000 :f
30 1100001 :y
31 1100010 :k
32 1100011 :p
33 110010 :l
34 110011 :g
35 110100 :c
36 110101 :v
37 11011 :d
38 111 :
39 I ask the indulgence of the children who may read this book for dedicating it to
40 a grown - up. I have a serious reason: he is the best friend I have in the world
41 . I have another reason: this grown - up understands everything
42 even books about children. I have a third reason: he lives in France where he is
43 hungry and cold. He needs cheering up.哈夫曼压缩后二进制序列:
44 10000011 10101001 01100010 11100001 01001111 10100101 11101100 01111001 01100110
45 11101111 01000111 11001111 00000111 00001010 01111111 01001010 01001100 1011011
46 1 00101110 11111100 01110100 01111100 01001101 01110000 11111001 01101011 101111
47 10 00010100 10000101 11000101 00110011 11000101 11110000 00011100 11111101 10111
48 101 10100110 10001010 00001001 01111001 11110100 00001110 00000111 11010111 1110
49 0111 00100111 00011101 11000100 00011110 00111000 01111111 10000011 11010010 111
50 01010 11111010 11110010 01110010 10000110 00110010 11110010 11010100 10001110 11
51 100010 11111010 01111101 00001011 10000101 00111110 00101011 00100000 11111000 0
52 0100101 00011101 11101111 11000001 11101001 01110101 01111101 00101111 10000101
53 00111111 00011001 11001110 01011011 10000111 11000001 11101001 01110101 01111101
54 01101100 11000010 10011100 11111001 01101010 01000111 01110001 01111000 0101001
55 0 00010111 11001110 01001110 00111011 10001000 00111100 01111100 01110111 101101
56 11 00100100 00001011 01111011 00101110 11110101 01110011 10000100 00101001 00101
57 111 00110001 00100111 10101011 10111110 00101001 10011110 00100010 11101010 0010
58 1001 10001100 00111110 10010100 10011001 01101110 01011101 11000011 11100000 111
59 10100 10111010 10111110 10111100 00101001 00100111 01111110 01011010 10010001 11
60 011100 01011111 01001111 11100100 10011010 10110010 11101001 01111100 01000010 0
61 1010110 11110100 01111110 00111010 01110010 11111101 00111110 10000101 11101000
62 01110111 10011100 11100001 11101011 01111011 11111010 00011110 01011011 10000111
63 10001000 10111111 01101101 11101100 10111110 10010100 11011100 10100101 1110011
64 1 11000111 10001110 0001
65 哈夫曼压缩打包假定文件格式二进制的文本体现:
66
67
68
69 (此处代码被截断,无法copy到剪贴板)
70
71 原字节数为: 341
72 压缩后字节数为: 181
73 压缩率为53. 2258 %
74 字符串字节数为: 341
75 字符串解压序列为:I ask the indulgence of the children who may read this book for
76 dedicating it to a grown - up. I have a serious reason: he is the best friend I
77 have in the world. I have another reason: this grown - up understands everything
78 even books about children. I have a third reason: he lives in France where he is
79 hungry and cold. He needs cheering up.
80
写到此处,我突然发现在进行位处理的时候,我并没有用一个更简化的方法(100行内可以解决)- -bnr ,好吧 下次写一个通用的压缩软件。