哈夫曼树与文件解压压缩C言代码
huffman压缩存储和解压缩源代码(精品文档)
![huffman压缩存储和解压缩源代码(精品文档)](https://img.taocdn.com/s3/m/d3a66f624431b90d6d85c735.png)
fst.open(filename, ifstream::in|ifstream::binary); wfile(fst, pssfile, Bytecode); fst.close(); pssfile.close(); system("pause"); }
void HuffmanCoding(array<huffman, m> &HT, array<string, n> &code, array<double, n> freq) { int j; unsigned char cj = 0; for (j = 0; j < n; ++j) { HT[cj].freq = freq[cj]; HT[cj].lchild = 0; HT[cj].rchild = 0; HT[cj].parent = 0; ++cj; } int i,s1, s2; for (i= n ; i <m; ++i) { myselect(HT, i, s1, s2); HT[s1].parent = i; HT[s2].parent = i; HT[i].lchild = s1; HT[i].rchild = s2; HT[i].freq = HT[s1].freq + HT[s2].freq; } for (i = 0; i < n; ++i) { string cd(n-1, '0'); int start = n-1; int k, f; for (k = i, f = HT[i].parent; f != 0; k = f, f = HT[f].parent) if (HT[f].lchild == k) cd[--start] = '0'; else cd[--start] = '1'; string cds(cd.substr(start, (n-1) - start)); code[i] = cds; }
c++哈夫曼树的文件压缩解压程序全部代码及设计报告
![c++哈夫曼树的文件压缩解压程序全部代码及设计报告](https://img.taocdn.com/s3/m/c4c07636192e45361066f5f9.png)
#include <iostream>#include <fstream>#include <queue> //队列容器using namespace std;const int leaf = 256; //最多可能出现的不同字符数const long MAX = 99999999; //表示无穷大typedef struct HTnode{long weight; //记录结点的权值int parent; //记录结点的双亲结点位置int lchild; //结点的左孩子int rchild; //结点的右孩子int *code; //记录该结点的huffman编码int codelen; //记录该结点huffman编码的长度HTnode(){weight = MAX;parent = -1;lchild = -1;rchild = -1;codelen = 0;}}HTnode;class huffmanTree{public:huffmanTree();virtual ~huffmanTree();bool count(char *input); //统计各字符出现的次数,将其写入对应结点的权值void create(); //构造huffman树void code(); //计算每个字符的huffman编码void addbit(int bit); //压缩时对一个未满8个bit的byte中加入一个bitvoid resetbyte(); //将byte清空bool compress(char *input, char *output); //压缩函数成功执行返回true 失败falsebool decompress(char *input, char *output); //解压函数成功执行返回true 失败falsevoid compare(char *input, char *output); //将原文件与压缩后的文件比较private:int root; //记录根结点的位置int leafnum; //记录不同字符的个数HTnode HT[leaf*2-1]; //HTnode结构的数组,用来表示huffman树,树的最大结点个数不会超过leaf*2-1char byte; //压缩文件时用来缓冲bit的变量int bitsnum; //byte中bit的个数int lacknum; //压缩到最后byte中的bit不满8个时填充的0的个数};huffmanTree::huffmanTree(){//初始化成员变量root = 0;leafnum = 0;byte = 0;bitsnum = 0;lacknum = 0;}huffmanTree::~huffmanTree(){for(int i=0; i<leaf; i++){if(HT[i].codelen != 0)delete []HT[i].code;}}//统计各字符出现的次数bool huffmanTree::count(char *input){ifstream ifs;char c;ifs.open(input,ios::binary);if(!ifs){cout << "无法打开文件" << input << '!' << endl;return false;}while(ifs.get(c)){if(HT[c+128].weight==MAX){ //若该字符是第一次出现,先初始化权值HT[c+128].weight = 0;leafnum++;}HT[c+128].weight++; //权值+1}ifs.close();return true;}//选权值最小的两棵树组成新的数void huffmanTree::create(){for(int i=leaf; i<2*leaf-1; i++){int loc1=-1, loc2=-1;for(int j=0; j<i; j++){if(HT[j].parent != -1)continue;if(loc1==-1 || HT[j].weight < HT[loc1].weight){loc2 = loc1;loc1 = j;}else if(loc2==-1 || HT[j].weight < HT[loc2].weight)loc2 = j;}if(HT[loc1].weight==MAX || HT[loc2].weight==MAX || loc2==-1) //只剩一棵树,结束break;HT[i].weight = HT[loc1].weight + HT[loc2].weight;//为了减少压缩文件中需要写入的huffman树的信息,约定小标小的结点做为双亲结点的左孩子HT[i].lchild = loc1>loc2 ? loc2 : loc1;HT[i].rchild = loc1>loc2 ? loc1 : loc2;HT[loc1].parent = i; HT[loc2].parent = i;root = i;}}//计算每个字符的huffman编码void huffmanTree::code(){for(int i=0; i<leaf; i++){int len=0;int loc=i;while(HT[loc].parent!=-1){ //计算huffman编码长度len++;loc = HT[loc].parent;}HT[i].codelen = len;HT[i].code = new int[len];loc = i;for(int j=len-1; j>=0; j--){ //从后往前找,记录结点的huffman编码if(loc==HT[HT[loc].parent].lchild)HT[i].code[j] = 0;elseHT[i].code[j] = 1;loc = HT[loc].parent;}}}//压缩时对一个未满8个bit的byte中加入一个bitvoid huffmanTree::addbit(int bit){if(bit == 0)byte = byte << 1; //若新增的bit为0,则直接将byte按位左移elsebyte = ((byte << 1) | 1); //若新增的bit为1,先将byte按位左移,再与1按位或运算bitsnum++;}//将byte清空void huffmanTree::resetbyte(){byte = 0;bitsnum = 0;}//压缩函数成功执行返回true 失败falsebool huffmanTree::compress(char *input, char *output){if( !count(input) )return false;create();code();ifstream ifs;ofstream ofs;ifs.open(input,ios::binary);ofs.open(output,ios::binary);char c;if(!ifs){cout << "无法打开文件" << input << '!' << endl;return false;}if(!ofs){cout << "无法打开文件" << output << '!' << endl;return false;}ofs.put(0); //预留一个字符,等压缩完后在该位置写入不足一个byte的bit个数ofs.put(root-384); //将根节点的位置-384写入(为使该值不超过char的最大表示范围)for(int i=0; i<leaf*2-1; i++){ //写入每个结点的双亲结点位置if(HT[i].parent==-1) //若该节点没有双亲结点,则写入127(一个字节所能表示的最大值)ofs.put(127);else //否则将双亲结点的位置-384再写入(为使该值不超过char的最大表示范围)ofs.put(HT[i].parent-384);}while(ifs.get(c)){ //将字符的huffman编码并加入byte中int tmp = c+128;for(int i=0; i<HT[tmp].codelen; i++){addbit(HT[tmp].code[i]);if(bitsnum==8){ //若byte已满8位,则输出该byte并将byte清空ofs.put(byte);resetbyte();}}}if(bitsnum!=0){ //处理最后未满8个字符的byte,用0填充并记录填充的个数for(int i=bitsnum; i<8; i++){addbit(0);lacknum++;}ofs.put(byte);resetbyte();}ofs.seekp(0,ios::beg); //将写指针移动到文件开头ofs.put(lacknum); //写入最后一个字节缺失的bit个数ifs.close();ofs.close();return true;}//解压函数成功执行返回true 失败falsebool huffmanTree::decompress(char *input, char *output){queue<char> q;char c;ifstream ifs;ofstream ofs;ifs.open(input,ios::binary);ofs.open(output,ios::binary);if(!ifs){cout << "无法打开文件" << input << '!' << endl;return true;}if(!ofs){cout << "无法打开文件" << output << '!' << endl;return false;}ifs.get(c);lacknum = c; //读出最后一个字节缺失的bit个数ifs.get(c);root = c+384; //读出根结点的位置for(int i=0; i<leaf*2-1; i++){ //建立各结点之间的双亲孩子关系ifs.get(c);if(c==127)continue;else{HT[i].parent = c+384;if(HT[c+384].lchild==-1)HT[c+384].lchild = i;elseHT[c+384].rchild = i;}}int point = root;//为了方便处理最后一个可能有缺失bit的字节,先将读出的数据放入队列while(ifs.get(c))q.push(c);//还原文件过程while(q.size()>1){ //还未到最后一个字节c = q.front();for(int i=0; i<8; i++){if(int(c&128)==0){point = HT[point].lchild;if(HT[point].lchild==-1 && HT[point].rchild==-1){ofs.put(char(point-128));point = root;}c = c << 1;}else{point = HT[point].rchild;if(HT[point].lchild==-1 && HT[point].rchild==-1){ofs.put(char(point-128));point = root;}c = c << 1;}}q.pop();}c = q.front(); //最后一个字节for(i=0; i<8-lacknum; i++){if(int(c&128)==0){point = HT[point].lchild;if(HT[point].lchild==-1 && HT[point].rchild==-1){ofs.put(char(point-128));point = root;}c = c << 1;}else{point = HT[point].rchild;if(HT[point].lchild==-1 && HT[point].rchild==-1){ofs.put(char(point-128));point = root;}c = c << 1;}}q.pop();ifs.close();ofs.close();return true;}//将原文件与压缩后的文件比较void huffmanTree::compare(char *input, char *output){ifstream origin, compress;origin.open(input,ios::binary);compress.open(output,ios::binary);if(!origin){cout << "无法打开文件" << input << '!' << endl;return;}if(!compress){cout << "无法打开文件" << output << '!' << endl;return;}double total1=0, total2=0;char c;while(origin.get(c))total1++;while(compress.get(c))total2++;cout << "原文件大小:" << total1 << " Byte" << endl;cout << "压缩后大小:" << total2 << " Byte" << endl;cout << "压缩率:" << total2/total1*100 << '%' << endl;origin.close();compress.close();}void main(){int choice = 1;char input[255], output[255];huffmanTree h;while(choice){cout<<" ****************************************************"<<endl;cout<<" * 基于哈夫曼树的文件压缩/解压程序*"<<endl;cout<<" * *"<<endl;cout<<" * 1) 压缩*"<<endl;cout<<" * *"<<endl;cout<<" * 2) 解压*"<<endl;cout<<" * *"<<endl;cout<<" * 0) 退出*"<<endl;cout<<" * *"<<endl;cout<<" * 说明:请输入相应的操作序号*"<<endl;cout<<" ****************************************************"<<endl;cout<<"请选择:";cin >> choice;switch(choice){case 1:{cout << "请输入待压缩的文件名:";cin >> input;cout << "请输入压缩后的文件名:";cin >> output;if( press(input,output)){pare(input,output);cout<<"文件压缩成功!"<<endl;}else{cout<<"文件压缩失败!"<<endl;}}break;case 2:{cout << "请输入待解压的文件名:";cin >> input;cout << "请输入解压后的文件名:";cin >> output;if (h.decompress(input,output))cout<<"文件解压成功!"<<endl;elsecout<<"文件解压失败!"<<endl;}break;case 0:break;default:cout << "参数错误!请重新输入" << endl;}cout << endl;}}韶关学院计算机科学学院数据结构课程设计题目:基于哈夫曼树的文件压缩/解压程序学生姓名:曹键明学号:11115011018专业:计算机科学与技术班级:11级(1)班指导教师姓名及职称:陈正铭讲师起止时间:2013 年3 月——2013 年4 月1 需求分析1.1课题背景及意义近年来,随着计算机技术的发展,多媒体计算机技术、计算机网络技术以及现代多媒体通信技术正在向着信息化、高速化、智能化迅速发展。
哈夫曼文本压缩C语言实现
![哈夫曼文本压缩C语言实现](https://img.taocdn.com/s3/m/1bd89bd476a20029bd642d5a.png)
}
//构造完毕
Lptr pop(int last)
{
int i;
Lptr head,p;
head=p=new Lnode;
for(i=0;i<last;i++)
{
p->c=co[i];
p->next=new Lnode;
p=>next;
}
p->c=-1;
{
printf("文件打开错误!\n");
exit(0);
}
while(!feof(fp))
{
p->c=fgetc(fp)&0xFF;
p->next=new Lnode;
p=p->next;
/*putchar(ch[i]);*/
i++;
}
putchar(10);
fclose(fp);
return(i-1);
j++;
}while(j%8);
return(y);
}
int restoretree(snode ch2[],int num2,int num1,char outfile[])
{
FILE*out1;
int i=0,j=0;
if((out1=fopen(outfile,"wb"))==NULL)
{
printf("文件打开错误!\n");
printf("还原结果:");
}
int putdata(Lptr strhead)//输入函数
{
哈夫曼压缩解压算法源码
![哈夫曼压缩解压算法源码](https://img.taocdn.com/s3/m/becd4714336c1eb91b375d10.png)
哈夫曼压缩解压算法源码HUFFMAN.C#include <alloc.h>#include <dos.h>#include <fcntl.h>main(argc, argv)int argc;char *argv[];{int f,er;int len,arc;char *inbuff;char *outbuff;char fname[80];char ch;if( argc < 2 ){puts( "Get me params !" );exit( 1 );}strcpy( fname,argv[1] );f = _open( fname,O_RDONLY );if( f < 0 ){puts( "Open error" );exit( 1 );}len = (int)filelength( f ); if( len < 0 ){puts( "File too large" ); exit( 1 );}inbuff = malloc( len );if( inbuff == NULL ){puts( "Not enough memory" ); exit( 1 );}len = _read( f,inbuff,len ); if( len < 0 ){puts( "Read error" );exit( 1 );}_close( f );if( !ntIsarc( inbuff+1 )){ outbuff = malloc( len );if( outbuff == NULL ){puts( "Not enough memory" ); exit( 1 );}printf( "Packing %s to ",fname );ch = *fname;*fname = '$';printf( "%s... ",fname );arc = ntEncode( outbuff,inbuff,len );if( arc == 0 ){puts( "Encode failure" );exit( 1 );}f = _creat( fname,FA_ARCH );if( f < 0 ){puts( "Create error" );exit( 1 );}er = _write( f,&ch,1 );er = _write( f,outbuff,arc );if( er < 0 ){puts( "Write error" );exit( 1 );}_close( f );printf( "Success. %.2f%%\n",((float)(len-arc)/(float)len)*100.0 ); }else{len = ntGetorig( inbuff+1 );outbuff = malloc( len );if( outbuff == NULL ){puts( "Not enough memory" );exit( 1 );}printf( "Unpacking %s to ",fname ); *fname = *inbuff;printf( "%s... ",fname );arc = ntDecode( outbuff,inbuff+1 ); if( arc == 0 ){puts( "Decode failure" );exit( 1 );}f = _creat( fname,FA_ARCH );if( f < 0 ){puts( "Create error" );exit( 1 );}er = _write( f,outbuff,len );if( er < 0 ){puts( "Write error" );exit( 1 );}_close( f );puts( "Success." );}}NTDECODE.C#define US 037#define RS 036char *_inp;char *_outp;int _origsize;short _dmaxlev;short _intnodes[25]; char *_tree[25]; char _characters[256]; char *_eof;int ntDecode( outbuff,inbuff )char *outbuff;char *inbuff;{int c, i, nchildren;int inleft;_eof = &_characters[0];if (inbuff[0] != US) return( 0 );if (inbuff[1] != RS) return( 0 );_inp = &inbuff[2];_origsize = 0;for (i=0; i<4; i++)_origsize = _origsize*256 + ((*_inp++) & 0377); inleft = _origsize;_dmaxlev = *_inp++ & 0377;if (_dmaxlev > 24) return( 0 );for (i=1; i<=_dmaxlev; i++)_intnodes[i] = *_inp++ & 0377;for (i=1; i<=_dmaxlev; i++) {_tree[i] = _eof;for (c=_intnodes[i]; c>0; c--) {if (_eof >= &_characters[255]) return( 0 );*_eof++ = *_inp++;}}*_eof++ = *_inp++;_intnodes[_dmaxlev] += 2;inleft -= _inp - &inbuff[0];if (inleft < 0) return( 0 );nchildren = 0;for (i=_dmaxlev; i>=1; i--) {c = _intnodes[i];_intnodes[i] = nchildren /= 2;nchildren += c;}return ( _decode( inleft,outbuff )); } _decode( inleft,outbuff )int inleft;char *outbuff;{int bitsleft, c, i;int j, lev;char *p;_outp = &outbuff[0];lev = 1;i = 0;while (1) {if (--inleft < 0) return( 0 );c = *_inp++;bitsleft = 8;while (--bitsleft >= 0) {i *= 2;if (c & 0200)i++;c <<= 1;if ((j = i - _intnodes[lev]) >= 0) { p = &_tree[lev][j];if (p == _eof){c = _outp - &outbuff[0];_origsize -= c;if (_origsize != 0) return( 0 );return (1);}*_outp++ = *p;lev = 1;i = 0;}elselev++;}}}NTENCODE.C#define END 256union FOUR {struct { long lng; } lint;struct { char c0, c1, c2, c3; } chars;};long _count[ END+1 ]; union FOUR _insize;int _diffbytes;int _maxlev;int _levcount[ 25 ]; int _lastnode;int _parent[ 2*END+1 ];char _length[ END+1 ]; long _bits[ END+1 ]; union FOUR _mask;long _inc;char *_maskshuff[4] = {&(_mask.chars.c3), &(_mask.chars.c2),&(_mask.chars.c1), &(_mask.chars.c0)};int _n_;struct _heap {long count;int node;} _heap[ END+2 ];#define hmove(a,b) {(b).count = (a).count; (b).node = (a).node;} int ntEncode( outbuff,inbuff,buflen ) char *outbuff;char *inbuff;int buflen;{register int c, i, p;long bitsout;_input( inbuff,buflen );_diffbytes = -1;_count[ END ] = 1;_insize.lint.lng = 0L;_n_ = 0;for (i=END; i>=0; i--) {_parent[i] = 0;if (_count[i] > 0) {_diffbytes++;_insize.lint.lng += _count[i];_heap[++_n_].count = _count[i];_heap[_n_].node = i;}}if (_diffbytes == 1) return( 0 );_insize.lint.lng >>= 1;for (i=_n_/2; i>=1; i--)_heapify(i);_lastnode = END;while (_n_ > 1) {_parent[_heap[1].node] = ++_lastnode; _inc = _heap[1].count;hmove (_heap[_n_], _heap[1]);_n_--;_heapify(1);_parent[_heap[1].node] = _lastnode; _heap[1].node = _lastnode;_heap[1].count += _inc;_heapify(1);}_parent[_lastnode] = 0;bitsout = _maxlev = 0;for (i=1; i<=24; i++)_levcount[i] = 0;for (i=0; i<=END; i++) {c = 0;for (p=_parent[i]; p!=0; p=_parent[p]) c++;_levcount[c]++;_length[i] = c;if (c > _maxlev)_maxlev = c;bitsout += c*(_count[i]>>1);}if (_maxlev > 24) return( 0 );_inc = 1L << 24;_inc >>= _maxlev;_mask.lint.lng = 0;for (i=_maxlev; i>0; i--) {for (c=0; c<=END; c++)if (_length[c] == i) {_bits[c] = _mask.lint.lng;_mask.lint.lng += _inc;}_mask.lint.lng &= ~_inc;_inc <<= 1;}return( _output( outbuff,inbuff,buflen )); }_input ( inbuff,buflen )char *inbuff;int buflen;{register int i;for (i=0; i<END; i++)_count[i] = 0;while (buflen > 0)_count[inbuff[--buflen]&0377] += 2; }int _output( outbuff,inbuff,buflen ) char *outbuff; char *inbuff;int buflen;{int c, i;char *inp;register char **q, *outp;register int bitsleft;long temp;outbuff[0] = 037; /* ascii US */outbuff[1] = 036; /* ascii RS */temp = _insize.lint.lng;for (i=5; i>=2; i--) {outbuff[i] = (char) (temp & 0377);temp >>= 8;}outp = outbuff+6;*outp++ = _maxlev;for (i=1; i<_maxlev; i++)*outp++ = _levcount[i];*outp++ = _levcount[_maxlev]-2;for (i=1; i<=_maxlev; i++)for (c=0; c<END; c++)if (_length[c] == i)*outp++ = c;inp = inbuff;bitsleft = 8;do {c = (--buflen < 0) ? END : (*inp++ & 0377); _mask.lint.lng = _bits[c]<<bitsleft;q = &_maskshuff[0];if (bitsleft == 8)*outp = **q++;else*outp |= **q++;bitsleft -= _length[c];while (bitsleft < 0) {*++outp = **q++;bitsleft += 8;}} while (c != END);if (bitsleft < 8)outp++;c = outp-outbuff;return (c);}_heapify( i )int i;{register int k;int lastparent;struct _heap heapsubi;hmove (_heap[i], heapsubi);lastparent = _n_/2;while (i <= lastparent) {k = 2*i;if (_heap[k].count > _heap[k+1].count && k < _n_) k++;if (heapsubi.count < _heap[k].count)break;hmove (_heap[k], _heap[i]);i = k;}hmove (heapsubi, _heap[i]); } NTGETORI.Cint ntGetorig( inbuff ) char *inbuff; {int i;char *in;int size;in = inbuff+2;size = 0;for (i=0; i<4; i++)size = size*256 + ((*in++) & 0377); return( size );}NTISARC.C#define US 037#define RS 036int ntIsarc( inbuff ) char *inbuff;{if( inbuff[0] == US && inbuff[1] == RS ) return( 1 );elsereturn( 0 );}。
用c语言编程实现用霍夫曼编码进行的数据压缩
![用c语言编程实现用霍夫曼编码进行的数据压缩](https://img.taocdn.com/s3/m/495a49c66137ee06eff91850.png)
用c语言编程实现用霍夫曼编码进行的数据压缩,需要完成以下功能:输入一个文档,声频,图像或者视频,能够对输入的这个原数据用霍夫曼编码的方式进行编码,压缩.请注意我的输入要求.#include <stdio.h>#include <string.h>#include <stdlib.h>#include <malloc.h>#include <conio.h>typedef struct {unsigned int weight;unsigned int parent,lchild,rchild;} HTNode,*HuffmanTree;typedef char **HuffmanCode;typedef struct {unsigned int s1;unsigned int s2;} MinCode;void Error(char *message);HuffmanCode HuffmanCoding(HuffmanTree HT,HuffmanCode HC,unsigned int*w,unsigned int n);MinCode Select(HuffmanTree HT,unsigned int n);void Error(char *message){clrscr();fprintf(stderr,"Error:%s\n",message);exit(1);}HuffmanCode HuffmanCoding(HuffmanTree HT,HuffmanCode HC,unsigned int*w,unsigned int n){unsigned int i,s1=0,s2=0;HuffmanTree p;char *cd;unsigned int f,c,start,m;MinCode min;if(n<=1) Error("Code too small!");m=2*n-1;HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); for(p=HT,i=0;i<=n;i++,p++,w++){p->weight=*w;p->parent=0;p->lchild=0;p->rchild=0;}for(;i<=m;i++,p++){p->weight=0;p->parent=0;p->lchild=0;p->rchild=0;}for(i=n+1;i<=m;i++){min=Select(HT,i-1);s1=min.s1;s2=min.s2;HT[s1].parent=i;HT[s2].parent=i;HT[i].lchild=s1;HT[i].rchild=s2;HT[i].weight=HT[s1].weight+HT[s2].weight;}printf("HT List:\n");printf("Number\t\tweight\t\tparent\t\tlchild\t\trchild\n"); for(i=1;i<=m;i++)printf("%d\t\t%d\t\t%d\t\t%d\t\t%d\n",i,HT[i].weight,HT[i].parent,HT[i].lchild,HT[i].rchild); HC=(HuffmanCode)malloc((n+1)*sizeof(char *));cd=(char *)malloc(n*sizeof(char *));cd[n-1]='\0';for(i=1;i<=n;i++){start=n-1;for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent)if(HT[f].lchild==c) cd[--start]='0';else cd[--start]='1';HC[i]=(char *)malloc((n-start)*sizeof(char *));strcpy(HC[i],&cd[start]);}free(cd);return HC;}MinCode Select(HuffmanTree HT,unsigned int n) {unsigned int min,secmin;unsigned int temp;unsigned int i,s1,s2,tempi;MinCode code;s1=1;s2=1;for(i=1;i<=n;i++)if(HT[i].parent==0){min=HT[i].weight;s1=i;break;}tempi=i++;for(;i<=n;i++)if(HT[i].weight<min&&HT[i].parent==0){min=HT[i].weight;s1=i;}for(i=tempi;i<=n;i++)if(HT[i].parent==0&&i!=s1){secmin=HT[i].weight;s2=i;break;}for(i=1;i<=n;i++)if(HT[i].weight<secmin&&i!=s1&&HT[i].parent==0) {secmin=HT[i].weight;s2=i;}if(s1>s2){temp=s1;s1=s2;s2=temp;}code.s1=s1;code.s2=s2;return code;}void main(){HuffmanTree HT=NULL;HuffmanCode HC=NULL;unsigned int *w=NULL;unsigned int i,n;clrscr();printf("Input n:\n");scanf("%d",&n);w=(unsigned int *)malloc((n+1)*sizeof(unsigned int *));w[0]=0;printf("Enter weight:\n");for(i=1;i<=n;i++){printf("w[%d]=",i);scanf("%d",&w[i]);}HC=HuffmanCoding(HT,HC,w,n);printf("HuffmanCode:\n");printf("Number\t\tWeight\t\tCode\n");for(i=1;i<=n;i++)printf("%d\t\t%d\t\t%s\n",i,w[i],HC[i]);}程序运行:首先用户先输入一个数n,以实现n个节点的Huffman Tree 之后输入权值w[1]~w[n],注意是unsigned int型数值。
C语言数据压缩哈夫曼编码和LZW算法
![C语言数据压缩哈夫曼编码和LZW算法](https://img.taocdn.com/s3/m/b3c12fb76429647d27284b73f242336c1fb93059.png)
C语言数据压缩哈夫曼编码和LZW算法C语言数据压缩——哈夫曼编码与LZW算法在计算机科学中,数据压缩是一种重要的技术,它可以有效地减少数据的存储空间和传输带宽。
本文将介绍两种常用的数据压缩算法,分别是哈夫曼编码和LZW算法,并给出它们在C语言中的实现方法。
一、哈夫曼编码1. 哈夫曼编码的原理哈夫曼编码是一种前缀编码方法,它根据字符出现的频率构建一棵表示编码的二叉树,频率越高的字符离根节点越近。
通过将二叉树的左、右分支分别标记为0和1,可以得到每个字符的唯一编码。
2. 实现哈夫曼编码的步骤(1)统计字符频率:遍历待压缩的数据,统计每个字符出现的频率。
(2)构建哈夫曼树:根据字符频率构建哈夫曼树,使用优先队列或堆来实现。
(3)生成哈夫曼编码表:通过遍历哈夫曼树,从根节点到各个叶子节点的路径上的0、1序列构建编码表。
(4)进行编码:根据生成的哈夫曼编码表,将待压缩数据转换为对应的编码。
(5)进行解码:利用哈夫曼树和生成的哈夫曼编码表,将编码解析为原始数据。
二、LZW算法1. LZW算法的原理LZW算法是一种字典压缩算法,它不需要事先进行字符频率统计,而是根据输入数据动态构建一个字典。
将输入数据中的序列与字典中的条目逐一匹配,若匹配成功则继续匹配下一个字符,若匹配失败则将当前序列加入字典,并输出该序列的编码。
2. 实现LZW算法的步骤(1)初始化字典:将所有可能的单字符作为字典的初始条目。
(2)读入输入数据:依次读入待压缩的数据。
(3)匹配字典:将读入的字符与字典中的条目逐一匹配,直到无法匹配成功。
(4)输出编码:将匹配成功的条目对应的编码输出。
(5)更新字典:若匹配失败,则将当前序列添加到字典中,并输出前一个匹配成功的条目对应的编码。
(6)重复步骤(3)至(5),直到输入数据全部处理完毕。
三、C语言实现1. 哈夫曼编码的C语言实现```c// TODO:哈夫曼编码的C语言实现```2. LZW算法的C语言实现```c// TODO:LZW算法的C语言实现```四、总结本文介绍了C语言中两种常用的数据压缩算法——哈夫曼编码和LZW算法。
哈夫曼树的构造c语言代码
![哈夫曼树的构造c语言代码](https://img.taocdn.com/s3/m/9b6d98e0185f312b3169a45177232f60ddcce7f9.png)
哈夫曼树的构造c语言代码哈夫曼树是一种特殊的二叉树,常被用于数据压缩中。
它的构造过程非常重要,接下来我将用c语言展示如何构造哈夫曼树。
首先,我们需要定义一个结构体作为节点:```struct Node{int weight;//权重int parent;//父节点在数组中的下标int lchild;//左子节点在数组中的下标int rchild;//右子节点在数组中的下标};```然后,我们需要读入数据,计算每个数据的权重,随后用一个数组存储节点信息:```int n;//数据个数int W[maxn];//存储每个数据的权重Node tree[maxn*2-1];//哈夫曼树```接下来,我们需要编写一个函数用来选择权值最小的两个节点,然后将它们合并成一个节点。
```int select_min(Node*tree,int n){int res=-1;int min=INT_MAX;for(int i=0;i<n;i++){if(tree[i].parent!=-1)continue;//跳过已经合并的节点if(tree[i].weight<min){min=tree[i].weight;res=i;}}return res;}void merge_node(Node*tree,int a,int b,int i){tree[a].parent=i;tree[b].parent=i;tree[i].weight=tree[a].weight+tree[b].weight;tree[i].lchild=a;tree[i].rchild=b;}```接下来,我们就可以开始构造哈夫曼树了。
我们先初始化每个节点,将它们都看成一个独立的树,然后选择最小的两个节点进行合并,直到最后只剩下一个树为止。
```void build_tree(Node*tree,int n,int*W){for(int i=0;i<n;i++){tree[i].weight=W[i];tree[i].parent=-1;tree[i].lchild=-1;tree[i].rchild=-1;}for(int i=n;i<(n<<1)-1;i++) {int a=select_min(tree,i);int b=select_min(tree,i);merge_node(tree,a,b,i);}}```最后,我们可以调用build_tree函数来构造哈夫曼树。
哈夫曼算法进行文件压缩和解压缩
![哈夫曼算法进行文件压缩和解压缩](https://img.taocdn.com/s3/m/5aba9c2c647d27284b735133.png)
本文首先简要阐述哈夫曼算法的基本思想,然后介绍了使用哈夫曼算法进行文件压缩和解压缩的处理步骤,最后给出了C语言实现的文件压缩和解压缩的源代码。
哈夫曼算法的主要思想是:①首先遍历要处理的字符串,得到每个字符的出现的次数;②将每个字符(以其出现次数为权值)分别构造为二叉树(注意此时的二叉树只有一个节点);③取所有二叉树种种字符出现次数最小的二叉树合并为一颗新的二叉树,新二叉树根节点的权值等于两个子节点的权值之和,新节点中的字符忽略;④重复过程③直到所有树被合并为同一棵二叉树⑤遍历最后得到的二叉树,自顶向下按路径编号,指向左节点的边编号0,指向右节点的边编号1,从根到叶节点的所有边上的0和1链接起来,就是叶子节点中字符的哈夫曼编码。
下图展示了哈夫曼编码的基本思想。
基于哈夫曼算法的文件压缩和解压缩过程分别说明如下:一、文件压缩:①统计词频:读取文件的每个字节,使用整数数组int statistic[MAX_CHARS]统计每个字符出现的次数,由于一个字节最多表示2^8-1个字符,所以MAX_CHARS=256就足够了。
在统计字符数的时候,对于每一个byte, 有statistic[(unsigned char)byte]++。
②构造哈夫曼树:根据statistic数组,基于哈夫曼树算法造哈夫曼树,由于构造的过程中每次都要取最小权值的字符,所以需要用优先队列来维护每棵树的根节点。
③生成编码:深度优先遍历哈弗曼树,得到每个叶子节点中的字符的编码并存入字符串数组char *dictionary[MAX_CHARS];④存储词频:新建存储压缩数据的文件,首先写入不同字符的个数,然后将每个字符及其对应的词频写入文件。
⑤存储压缩数据:再次读取待压缩文件的每个字节byte,由dictionary[(unsigned int)byte]得到对应的编码(注意每个字符编码的长度不一),使用位运算一次将编码中的每个位(BIT)设置到一个char 类型的位缓冲中,可能多个编码才能填满一个位缓冲,每填满一次,将位缓冲区以单个字节的形式写入文件。
哈夫曼树压缩文件代码
![哈夫曼树压缩文件代码](https://img.taocdn.com/s3/m/d8106f13abea998fcc22bcd126fff705cc175cac.png)
哈夫曼树压缩文件代码哈夫曼树压缩文件是一种常用的数据压缩技术,可以将大量重复出现的数据压缩成较小的文件,从而节省存储空间和传输带宽。
下面是一个简单的哈夫曼树压缩文件的代码示例:```pythonimport heapqimport osclass HuffmanCoding:def __init__(self, path):self.path = pathself.heap = []self.codes = {}self.reverse_codes = {}class HeapNode:def __init__(self, char, freq):self.char = charself.freq = freqself.left = Noneself.right = Nonedef __lt__(self, other):return self.freq < other.freqdef make_frequency_dict(self, text):frequency = {}for character in text:if character not in frequency:frequency[character] = 0frequency[character] += 1return frequencydef make_heap(self, frequency):for key in frequency:node = self.HeapNode(key, frequency[key])heapq.heappush(self.heap, node)def merge_codes(self):while len(self.heap) > 1:node1 = heapq.heappop(self.heap)node2 = heapq.heappop(self.heap)merged = self.HeapNode(None, node1.freq + node2.freq) merged.left = node1merged.right = node2heapq.heappush(self.heap, merged)def make_codes_helper(self, root, current_code):if root is None:returnif root.char is not None:self.codes[root.char] = current_codeself.reverse_codes[current_code] = root.charreturnself.make_codes_helper(root.left, current_code + '0') self.make_codes_helper(root.right, current_code + '1') def make_codes(self):root = heapq.heappop(self.heap)current_code = ''self.make_codes_helper(root, current_code)def get_encoded_text(self, text):encoded_text = ''for character in text:encoded_text += self.codes[character]return encoded_textdef pad_encoded_text(self, encoded_text):padding = 8 - len(encoded_text) % 8for i in range(padding):encoded_text += '0'padded_info = '{0:08b}'.format(padding)encoded_text = padded_info + encoded_textreturn encoded_textdef get_byte_array(self, padded_encoded_text):if len(padded_encoded_text) % 8 != 0:print('Encoded text not padded properly')exit(0)b = bytearray()for i in range(0, len(padded_encoded_text), 8):byte = padded_encoded_text[i:i + 8]b.append(int(byte, 2))return bdef compress(self):filename, file_extension = os.path.splitext(self.path)output_path = filename + '.bin'with open(self.path, 'r+') as file, open(output_path, 'wb') as output:text = file.read()text = text.rstrip()frequency = self.make_frequency_dict(text)self.make_heap(frequency)self.merge_codes()self.make_codes()encoded_text = self.get_encoded_text(text)padded_encoded_text =self.pad_encoded_text(encoded_text)b = self.get_byte_array(padded_encoded_text)output.write(bytes(b))print('Compressed')return output_pathdef remove_padding(self, padded_encoded_text):padded_info = padded_encoded_text[:8]padding = int(padded_info, 2)padded_encoded_text = padded_encoded_text[8:]encoded_text = padded_encoded_text[:-1 * padding]return encoded_textdef decode_text(self, encoded_text):current_code = ''decoded_text = ''for bit in encoded_text:current_code += bitif current_code in self.reverse_codes:character = self.reverse_codes[current_code]decoded_text += charactercurrent_code = ''return decoded_textdef decompress(self, input_path):filename, file_extension = os.path.splitext(self.path)output_path = filename + '_decompressed' + '.txt'with open(input_path, 'rb') as file, open(output_path, 'w') as output:bit_string = ''byte = file.read(1)while byte:byte = ord(byte)bits = bin(byte)[2:].rjust(8, '0')bit_string += bitsbyte = file.read(1)encoded_text = self.remove_padding(bit_string)decoded_text = self.decode_text(encoded_text)output.write(decoded_text)print('Decompressed')return output_path```使用此代码,您可以将文本文件压缩为二进制文件,并将其解压缩回原始文本格式。
用c语言实现哈夫曼编码
![用c语言实现哈夫曼编码](https://img.taocdn.com/s3/m/daf3900468eae009581b6bd97f1922791788be12.png)
用c语言实现哈夫曼编码哈夫曼编码是一种用于无损数据压缩的熵编码算法。
以下是一个简单的使用C语言实现哈夫曼编码的例子。
这个例子只实现了编码过程,没有实现解码过程。
c复制代码#include<stdio.h>#include<stdlib.h>#include<string.h>// 节点结构体typedef struct Node {char data;int freq;struct Node *left, *right;} Node;// 创建新节点Node* newNode(char data, int freq) {Node* node = (Node*) malloc(sizeof(Node));node->data = data;node->freq = freq;node->left = node->right = NULL;return node;}// 计算前缀和int getSum(Node* root) {if (!root) return0;return root->freq + getSum(root->left) + getSum(root->right);}// 创建哈夫曼树Node* createHuffmanTree(char data[], int freq[], int size) { if (size == 0) return NULL;Node *left = newNode(data[size-1], freq[size-1]);Node *right = createHuffmanTree(data, freq, size-1);Node *top = newNode(0, getSum(right));top->left = left;top->right = right;return top;}// 打印哈夫曼编码void printHuffmanCode(Node* root, int n, char code[]) {if (!root) return;if (root->data != 0) printf("%c: ", root->data);code[n] = root->data;printHuffmanCode(root->left, n+1, code);printHuffmanCode(root->right, n+1, code);}int main() {char data[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};int freq[] = {5, 9, 12, 13, 16, 45};int size = sizeof(data)/sizeof(data[0]);Node* root = createHuffmanTree(data, freq, size);char code[256] = {0}; // 存放哈夫曼编码,初始为空字符串,表示没有编码,对应字符的编码为空字符串。
用哈夫曼树算法写对文件压缩与解压缩代码
![用哈夫曼树算法写对文件压缩与解压缩代码](https://img.taocdn.com/s3/m/ae6524da6f1aff00bed51e7d.png)
用哈夫曼树算法设计对文件文件的压缩和解压缩的程序怎么写?基本要求:(1)文件名的输入可以从命令行给出或程序界面给出;(2)压缩和解压选择也可以从命令行给出或程序界面给出;(3)给出压缩后的指标:压缩率=压缩后的文件大小/压缩前的文件大小最佳答案#include <stdio.h>#include <string.h>#include <stdlib.h>#include <conio.h>struct head{unsigned char b; /*the charactor*/long count; /*the frequency*/long parent,lch,rch; /*make a tree*/char bits[256]; /*the haffuman code*/}header[512],tmp;void compress(){char filename[255],outputfile[255],buf[512];unsigned char c;long i,j,m,n,f;long min1,pt1,flength;FILE *ifp,*ofp;printf("source filename:");gets(filename);ifp=fopen(filename,"rb");if(ifp==NULL){printf("source file open error!\n");return;}printf("destination filename:");gets(outputfile);ofp=fopen(outputfile,"wb");if(ofp==NULL){printf("destination file open error!\n");return;}flength=0;while(!feof(ifp)){fread(&c,1,1,ifp);header[c].count++;flength++;}flength--;header[c].count--;for(i=0;i<512;i++){if(header[i].count!=0) header[i].b=(unsigned char)i; else header[i].b=0;header[i].parent=-1;header[i].lch=header[i].rch=-1;}for(i=0;i<256;i++){for(j=i+1;j<256;j++){if(header[i].count<header[j].count){tmp=header[i];header[i]=header[j];header[j]=tmp;}}}for(i=0;i<256;i++) if(header[i].count==0) break;n=i;m=2*n-1;for(i=n;i<m;i++){min1=999999999;for(j=0;j<i;j++){if(header[j].parent!=-1) continue;if(min1>header[j].count){pt1=j;min1=header[j].count;continue;}}header[i].count=header[pt1].count;header[pt1].parent=i;header[i].lch=pt1;min1=999999999;for(j=0;j<i;j++){if(header[j].parent!=-1) continue;if(min1>header[j].count){pt1=j;min1=header[j].count;continue;}}header[i].count+=header[pt1].count;header[i].rch=pt1;header[pt1].parent=i;}for(i=0;i<n;i++){f=i;header[i].bits[0]=0;while(header[f].parent!=-1){j=f;f=header[f].parent;if(header[f].lch==j){j=strlen(header[i].bits);memmove(header[i].bits+1,header[i].bits,j+1);header[i].bits[0]='0';}else\ {j=strlen(header[i].bits);memmove(header[i].bits+1,header[i].bits,j+1);header[i].bits[0]='1';}}}fseek(ifp,0,SEEK_SET);fwrite(&flength,sizeof(int),1,ofp);fseek(ofp,8,SEEK_SET);buf[0]=0;f=0;pt1=8;while(!feof(ifp)){c=fgetc(ifp);f++;for(i=0;i<n;i++){if(c==header[i].b) break;}strcat(buf,header[i].bits);j=strlen(buf);c=0;while(j>=8){for(i=0;i<8;i++){if(buf[i]=='1') c=(c<<1)|1;else c=c<<1;}fwrite(&c,1,1,ofp);pt1++;strcpy(buf,buf+8);j=strlen(buf);}if(f==flength) break;}if(j>0){strcat(buf,"00000000");for(i=0;i<8;i++){if(buf[i]=='1') c=(c<<1)|1;else c=c<<1;}fwrite(&c,1,1,ofp);pt1++;}fseek(ofp,4,SEEK_SET);fwrite(&pt1,sizeof(long),1,ofp); fseek(ofp,pt1,SEEK_SET);fwrite(&n,sizeof(long),1,ofp);for(i=0;i<n;i++){fwrite(&(header[i].b),1,1,ofp);c=strlen(header[i].bits);fwrite(&c,1,1,ofp);j=strlen(header[i].bits);if(j%8!=0){for(f=j%8;f<8;f++)strcat(header[i].bits,"0");}while(header[i].bits[0]!=0){c=0;for(j=0;j<8;j++){if(header[i].bits[j]=='1') c=(c<<1)|1;else c=c<<1;}strcpy(header[i].bits,header[i].bits+8);fwrite(&c,1,1,ofp);}}fclose(ifp);fclose(ofp);printf("compress successfully!\n");return;}void uncompress(){char filename[255],outputfile[255],buf[255],bx[255]; unsigned char c;long i,j,m,n,f,p,l;long flength;FILE *ifp,*ofp;printf("source filename:");gets(filename);ifp=fopen(filename,"rb");if(ifp==NULL){printf("source file open error!\n");return;}printf("destination filename:");gets(outputfile);ofp=fopen(outputfile,"wb");if(ofp==NULL){printf("destination file open error!\n"); return;}fread(&flength,sizeof(long),1,ifp);fread(&f,sizeof(long),1,ifp);fseek(ifp,f,SEEK_SET);fread(&n,sizeof(long),1,ifp);for(i=0;i<n;i++){fread(&header[i].b,1,1,ifp);fread(&c,1,1,ifp);p=(long)c;header[i].count=p;header[i].bits[0]=0;if(p%8>0) m=p/8+1;else m=p/8;for(j=0;j<m;j++){fread(&c,1,1,ifp);f=c;itoa(f,buf,2);f=strlen(buf);for(l=8;l>f;l--){strcat(header[i].bits,"0");}strcat(header[i].bits,buf);}header[i].bits[p]=0;}for(i=0;i<n;i++){for(j=i+1;j<n;j++){if(strlen(header[i].bits)>strlen(header[j].bits)) {tmp=header[i];header[i]=header[j];header[j]=tmp;}}}p=strlen(header[n-1].bits);fseek(ifp,8,SEEK_SET);m=0;bx[0]=0;while(1){while(strlen(bx)<(unsigned int)p){fread(&c,1,1,ifp);f=c;itoa(f,buf,2);f=strlen(buf);for(l=8;l>f;l--){strcat(bx,"0");}strcat(bx,buf);}for(i=0;i<n;i++){if(memcmp(header[i].bits,bx,header[i].count)==0) break; }strcpy(bx,bx+header[i].count);c=header[i].b;fwrite(&c,1,1,ofp);m++;if(m==flength) break;}fclose(ifp);fclose(ofp);printf("Uncompress successfully!\n");return;}int main(){int c;printf("1--Compress file\n");printf("2--Uncompress file\n");printf("Select 1 or 2:");c=getch();printf("%c\n",c);if(c=='1') compress();else if(c=='2') uncompress();return 0;}。
哈夫曼树与文件解压压缩C言代码
![哈夫曼树与文件解压压缩C言代码](https://img.taocdn.com/s3/m/1cbae1712e3f5727a5e962cf.png)
哈夫曼树与文件解压压缩C言代码1.问题描述哈弗曼树的编码与译码—功能:实现对任何类型文件的压缩与解码—输入:源文件,压缩文件—输出:解码正确性判定,统计压缩率、编码与解码速度—要求:使用边编码边统计符号概率的方法(自适应Huffman编码)和事先统计概率的方法(静态Huffman编码)2.1程序清单程序书签:1.main函数2.压缩函数3.select函数4.encode函数5.解压函数#include <stdio.h>#include <string.h>#include <stdlib.h>#include <conio.h>#include <time.h>struct node{long weight; //权值unsigned char ch;//字符int parent,lchild,rchild;char code[256];//编码的位数最多为256位int CodeLength;//编码长度}hfmnode[512];void compress();void uncompress();//主函数void main(){int choice;printf("请选择1~3:\n");printf("1.压缩文件\n");printf("2.解压文件\n");printf("3.退出!\n");scanf("%d",&choice);if(choice==1)compress();else if(choice==2)uncompress();else if(choice==3)return;else printf("输入错误!");}//压缩函数void compress(){int i,j;char infile[20],outfile[20];FILE *ifp,*ofp;unsigned char c;//long FileLength,filelength=0;int n,m;//叶子数和结点数int s1,s2; //权值最小的两个结点的标号char codes[256];long sumlength=0;float rate,speed;int count=0;clock_t start1, start2,finish1,finish2;double duration1,duration2;void encode(struct node *nodep,int n);//编码函数int select(struct node *nodep,int pose);//用于建哈弗曼树中选择权值最小的结点的函数printf("请输入要压缩的文件名:");scanf("%s",infile);ifp=fopen(infile,"rb");if(ifp==NULL){printf("文件名输入错误,文件不存在!\n");return;}printf("请输入目标文件名:");scanf("%s",outfile);ofp=fopen(outfile,"wb");if(ofp==NULL){printf("文件名输入错误,文件不存在!\n");return;}start1=clock() ;//开始计时1//统计文件中字符的种类以及各类字符的个数//先用字符的ASCII码值代替结点下标FileLength=0;while(!feof(ifp)){fread(&c,1,1,ifp);hfmnode[c].weight++;FileLength++;}FileLength--; //文件中最后一个字符的个数会多统计一次,所以要减一hfmnode[c].weight--;//再将ASCII转换为字符存入到结点的ch成员里,同时给双亲、孩子赋初值-1n=0;for(i=0;i<256;i++)if(hfmnode[i].weight!=0){hfmnode[i].ch=(unsigned char)i;n++;//叶子数hfmnode[i].lchild=hfmnode[i].rchild=hfmnode[i].parent=-1;}m=2*n-1;//哈弗曼树结点总数j=0;for(i=0;i<256;i++)//去掉权值为0的结点if(hfmnode[i].weight!=0){hfmnode[j]=hfmnode[i];j++;}for(i=n;i<m;i++)//初始化根结点{hfmnode[i].lchild=hfmnode[i].rchild=-1;hfmnode[i].parent=-1;}//建立哈弗曼树for(i=n;i<m;i++){s1=select(hfmnode,i-1);hfmnode[i].lchild=s1;hfmnode[s1].parent=i;s2=select(hfmnode,i-1);hfmnode[i].rchild=s2;hfmnode[s2].parent=i;hfmnode[i].weight=hfmnode[s1].weight+hfmnode[s2].weight;}//编码encode(hfmnode,n);finish1=clock();duration1=(double)(finish1- start1) / CLOCKS_PER_SEC;/*printf( "哈弗曼树编码用时为:%f seconds\n", duration1 );*/printf("编码完成,是否查看编码信息: y or n?\n");c=getch();if(c=='y'){ printf("\n");printf("叶子数为%d,结点数为%d\n",n,m);for(i=0;i<n;i++)printf("%d号叶子结点的权值为:%ld,双亲为:%d,左右孩子:%d,编码为:%s\n",i,hfmnode[i].weight,hfmnode[i].parent,hfmnode[i].lchild,hfmnode[i].code);}start2=clock() ;//开始计时2fseek(ifp,0,SEEK_SET);//将ifp指针移到文件开头位置fwrite(&FileLength,4,1,ofp);//将FileLength写入目标文件的前4个字节的位置fseek(ofp,8,SEEK_SET);//再将目标文件指针ofp移到距文件开头8个字节位置codes[0]=0;//将编码信息写入目标文件while(!feof(ifp)){fread(&c,1,1,ifp);filelength++;for(i=0;i<n;i++)if(c==hfmnode[i].ch) break; //ch必须也为unsigned 型strcat(codes,hfmnode[i].code);while(strlen(codes)>=8){for(i=0;i<8;i++)//将codes的前8位01代码表示的字符存入c{if(codes[i]=='1')c=(c<<1)|1;else c=c<<1;}fwrite(&c,1,1,ofp); //将新的字符写入目标文件sumlength++;strcpy(codes,codes+8);//更新codes的值}if(filelength==FileLength) break;}//再将剩余的不足8位的01代码补全8位,继续写入if(strlen(codes)>0){strcat(codes,"00000000");for(i=0;i<8;i++){if(codes[i]=='1')c=(c<<1)|1;else c=c<<1;}fwrite(&c,1,1,ofp);sumlength++;}sumlength+=8;printf("编码区总长为:%ld个字节\n",sumlength-8);//将sumlength和n的值写入目标文件,为的是方便解压fseek(ofp,4,SEEK_SET);fwrite(&sumlength,4,1,ofp);//把sumlength写进目标文件的第5-8个字节里fseek(ofp,sumlength,SEEK_SET);fwrite(&n,4,1,ofp);//把叶子数n写进编码段后面的4个字节的位置//为方便解压,把编码信息存入n后面的位置//存储方式为:n*(字符值(1个字节)+该字符的01编码的位数(1个字节)+编码(字节数不确定,用count来计算总值))for(i=0;i<n;i++){fwrite(&(hfmnode[i].ch),1,1,ofp);c=hfmnode[i].CodeLength;//编码最长为256位,因此只需用一个字节存储fwrite(&c,1,1,ofp);//写入字符的编码if(hfmnode[i].CodeLength%8!=0)for(j=hfmnode[i].CodeLength%8;j<8;j++)//把编码不足8位的在低位补0,赋值给C,再把C写入strcat(hfmnode[i].code,"0");while(hfmnode[i].code[0]!=0)//开始存入编码,每8位二进制数存入一个字节{c=0;for(j=0;j<8;j++){if(hfmnode[i].code[j]=='1')c=(c<<1)|1;else c=c<<1;}strcpy(hfmnode[i].code,hfmnode[i].code+8);//编码前移8位,继续存入编码count++; //编码占的字节数的总值fwrite(&c,1,1,ofp);}}printf("\n");finish2=clock();duration2=(double)(finish2- start2) / CLOCKS_PER_SEC;/*printf( "写入目标文件用时为:%f seconds\n", duration2);*/printf( "压缩用时为:%f seconds\n", duration1+duration2);speed=(float)FileLength/(duration1+duration2)/1000;printf("\n压缩速率为:%5.2f KB/S\n",speed);printf("\n");printf("源文件长度为:%ld个字节\n",FileLength);sumlength=sumlength+4+n*2+count; //计算压缩后文件的长度printf("压缩后文件长度为:%ld个字节\n",sumlength);rate=(float)sumlength/(float)FileLength;printf("压缩率(百分比)为:%4.2f%%%\n",rate*100);fclose(ifp);fclose(ofp);return;}//返回书签//建立哈弗曼树中用于选择最小权值结点的函数int select(struct node *nodep,int pose){int i;int s1;long min=2147483647;//s初值为long型的最大值for(i=0;i<=pose;i++){if(nodep[i].parent!=-1)continue;if(nodep[i].weight<min){min=nodep[i].weight;s1=i;}}return s1;}//返回书签//哈弗曼编码函数void encode(struct node *nodep,int n){ //从叶子向根求每个字符的哈弗曼编码int start;int i,f,c;char codes[256];codes[n-1]='\0'; //编码结束符for(i=0;i<n;i++) //逐个字符求哈弗曼编码{start=n-1;for(c=i,f=nodep[i].parent;f!=-1;c=f,f=nodep[f].parent){start--;if(nodep[f].lchild==c)codes[start]='0';else codes[start]='1';}strcpy(nodep[i].code,&codes[start]);nodep[i].CodeLength=strlen(nodep[i].code);}}//返回书签//解压函数void uncompress() //解压文件{clock_t start, finish;double duration;FILE *ifp,*ofp;char infile[20],outfile[20];long FileLength,sumlength,filelength;int n,m;int i,j,k;char buf[256],codes[256];unsigned char c;int maxlength;float speed;printf("请输入要解压的文件名:");scanf("%s",infile);ifp=fopen(infile,"rb");if(ifp==NULL){printf("文件名输入错误,文件不存在!\n");return;}printf("请输入目标文件名:");scanf("%s",outfile);ofp=fopen(outfile,"wb");if(ofp==NULL){printf("文件名输入错误,文件不存在!\n");return;}start=clock() ;//开始计时fread(&FileLength,4,1,ifp);//从压缩文件读出FileLength、sumlengthfread(&sumlength,4,1,ifp);fseek(ifp,sumlength,SEEK_SET); //利用sumlength读出n的值fread(&n,4,1,ifp);printf("\n解码信息:源文件长度为%d个字节,字符种类n=%d\n",FileLength,n);for(i=0;i<n;i++)//读结点信息{fread(&hfmnode[i].ch,1,1,ifp);//字符fread(&c,1,1,ifp);//编码长度hfmnode[i].CodeLength=c;hfmnode[i].code[0]=0;if(hfmnode[i].CodeLength%8>0) m=hfmnode[i].CodeLength/8+1;//m为编码占的字节数else m=hfmnode[i].CodeLength/8;for(j=0;j<m;j++)//根据字节长度m读出编码{fread(&c,1,1,ifp);//此处c为01编码转换成的字符itoa(c,buf,2);//字符型编码转换成二进制型(首位为1)//如果编码不够8位,则说明缺少了8-k位0,因此应先在前面空缺位写0for(k=8;k>strlen(buf);k--){strcat(hfmnode[i].code,"0");}//再把二进制编码存进hfmnode.code中strcat(hfmnode[i].code,buf);}hfmnode[i].code[hfmnode[i].CodeLength]=0;//去掉编码中多余的0 }//找出编码长度的最大值maxlength=0;for(i=0;i<n;i++)if(hfmnode[i].CodeLength>maxlength)maxlength=hfmnode[i].CodeLength;//开始写入目标文件fseek(ifp,8,SEEK_SET); //指针指向编码区,开始解码filelength=0;codes[0]=0;buf[0]=0;while(1){while(strlen(codes)<maxlength)//codes小于编码长度的最大值时,继续读码{fread(&c,1,1,ifp);itoa(c,buf,2);//还原编码for(k=8;k>strlen(buf);k--){strcat(codes,"0");//把缺掉的0补上}strcat(codes,buf);//codes中此时存的为一串01编码}for(i=0;i<n;i++){ //在codes中查找能使其前weight位和hfmnode.code相同的i值,weight 即为codelengthif(memcmp(hfmnode[i].code,codes,(unsignedint)hfmnode[i].CodeLength)==0) break;}strcpy(codes,codes+hfmnode[i].CodeLength);//更新codes的值c=hfmnode[i].ch;fwrite(&c,1,1,ofp);filelength++;if(filelength==FileLength) break;//写入结束}finish = clock();duration = (double)(finish - start) / CLOCKS_PER_SEC;printf( "\n解压完成,解压用时为:%f seconds\n", duration );fseek(ifp,0,SEEK_SET);FileLength=0;while(!feof(ifp)){fread(&c,1,1,ifp);FileLength++;}FileLength--;speed=(float)FileLength/duration/1000;/*printf("此文件长度为:%ld个字节\n",FileLength);*/printf("\n解压速度为:%5.2fKB/S\n",speed);fclose(ifp);fclose(ofp);return;}2.2程序运行结果:1.对文件”测试.txt”进行压缩,压缩后存储在文件”目标.doc”中,压缩速率为:2055.00KB/S,压缩率为64.92%。
基于哈夫曼(haffuman)算法的文件压缩的实现(C语言)(转)
![基于哈夫曼(haffuman)算法的文件压缩的实现(C语言)(转)](https://img.taocdn.com/s3/m/70d32bd06037ee06eff9aef8941ea76e58fa4aa3.png)
基于哈夫曼(haffuman)算法的⽂件压缩的实现(C语⾔)(转)本⽂⾸先简要阐述哈夫曼算法的基本思想,然后介绍了使⽤哈夫曼算法进⾏⽂件压缩和解压缩的处理步骤,最后给出了C语⾔实现的⽂件压缩和解压缩的源代码。
哈夫曼算法的主要思想是:①⾸先遍历要处理的字符串,得到每个字符的出现的次数;②将每个字符(以其出现次数为权值)分别构造为⼆叉树(注意此时的⼆叉树只有⼀个节点);③取所有⼆叉树种种字符出现次数最⼩的⼆叉树合并为⼀颗新的⼆叉树,新⼆叉树根节点的权值等于两个⼦节点的权值之和,新节点中的字符忽略;④重复过程③直到所有树被合并为同⼀棵⼆叉树⑤遍历最后得到的⼆叉树,⾃顶向下按路径编号,指向左节点的边编号0,指向右节点的边编号1,从根到叶节点的所有边上的0和1链接起来,就是叶⼦节点中字符的哈夫曼编码。
下图展⽰了哈夫曼编码的基本思想。
基于哈夫曼算法的⽂件压缩和解压缩过程分别说明如下:⼀、⽂件压缩:①统计词频:读取⽂件的每个字节,使⽤整数数组int statistic[MAX_CHARS]统计每个字符出现的次数,由于⼀个字节最多表⽰2^8-1个字符,所以MAX_CHARS=256就⾜够了。
在统计字符数的时候,对于每⼀个byte, 有statistic[(unsigned char)byte] 。
②构造哈夫曼树:根据statistic数组,基于哈夫曼树算法造哈夫曼树,由于构造的过程中每次都要取最⼩权值的字符,所以需要⽤优先队列来维护每棵树的根节点。
③⽣成编码:深度优先遍历哈弗曼树,得到每个叶⼦节点中的字符的编码并存⼊字符串数组char*dictionary[MAX_CHARS];④存储词频:新建存储压缩数据的⽂件,⾸先写⼊不同字符的个数,然后将每个字符及其对应的词频写⼊⽂件。
⑤存储压缩数据:再次读取待压缩⽂件的每个字节byte,由dictionary[(unsigned int)byte]得到对应的编码(注意每个字符编码的长度不⼀),使⽤位运算⼀次将编码中的每个位(BIT)设置到⼀个char类型的位缓冲中,可能多个编码才能填满⼀个位缓冲,每填满⼀次,将位缓冲区以单个字节的形式写⼊⽂件。
哈夫曼树压缩CPP实现
![哈夫曼树压缩CPP实现](https://img.taocdn.com/s3/m/321db62f2f60ddccda38a05c.png)
//
// calculte the frequency of character occurence in a file and put
// them to a Haffman_tree::freq_table
YLib::Haffman_tree::freq_table get_frequency_table_imp(std::istream& in)
{
typedef YLib::Haffman_tree::freq_table freq_table;
typedef YLib::byte_t byte_t;
#include <string>
#include <map>
namespace YLib {
typedef unsigned char byte_t;
typedef std::basic_string<byte_t> byte_string;
// note that in my design a Huffman_tree is simply a
};
struct Cmp_by_freq {
typedef Haffman_node* value_t;
bool operator()(const value_t& left, const value_t& right) const
bool empty() const { return code_table_.empty(); }
iterator begin() { return code_table_.begin(); }
c语言实现构造哈夫曼树代码
![c语言实现构造哈夫曼树代码](https://img.taocdn.com/s3/m/3eab01c8900ef12d2af90242a8956bec0975a531.png)
c语言实现构造哈夫曼树代码一、哈夫曼树简介哈夫曼树是一种特殊的二叉树,其每个叶子节点都对应一个权值,而非叶子节点则没有权值。
哈夫曼树的构造过程中,将权值较小的节点放在左子树,权值较大的节点放在右子树,这使得哈夫曼树的带权路径最短。
哈夫曼编码就是利用这种特性实现对数据进行压缩。
二、C语言实现构造哈夫曼树1. 定义结构体首先需要定义一个结构体来表示哈夫曼树中的节点。
结构体中包含了该节点的权值以及指向左右子节点的指针。
```typedef struct TreeNode {int weight;struct TreeNode *left;struct TreeNode *right;} TreeNode;2. 构造哈夫曼树接下来需要实现构造哈夫曼树的函数。
该函数接收一个数组作为输入,数组中存储了每个叶子节点的权值。
首先需要将数组中所有元素转化为TreeNode类型,并将它们存储在一个链表中。
```TreeNode *createTreeNodes(int weights[], int size) {TreeNode *nodes[size];for (int i = 0; i < size; i++) {nodes[i] = (TreeNode *)malloc(sizeof(TreeNode));nodes[i]->weight = weights[i];nodes[i]->left = NULL;nodes[i]->right = NULL;}return nodes;}```接下来,需要实现一个函数来找到权值最小的两个节点。
该函数接收一个链表作为输入,并返回该链表中权值最小的两个节点。
```void findMinNodes(TreeNode **nodes, int size, TreeNode**minNode1, TreeNode **minNode2) {*minNode1 = *minNode2 = NULL;for (int i = 0; i < size; i++) {if (*minNode1 == NULL || (*nodes)[i].weight <(*minNode1)->weight) {*minNode2 = *minNode1;*minNode1 = &(*nodes)[i];} else if (*minNode2 == NULL || (*nodes)[i].weight < (*minNode2)->weight) {*minNode2 = &(*nodes)[i];}}}```接下来,需要实现一个函数来构造哈夫曼树。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1.问题描述哈弗曼树的编码与译码—功能:实现对任何类型文件的压缩与解码—输入:源文件,压缩文件—输出:解码正确性判定,统计压缩率、编码与解码速度—要求:使用边编码边统计符号概率的方法(自适应Huffman编码)和事先统计概率的方法(静态Huffman编码)2.1程序清单程序书签:1.main函数2.压缩函数3.select函数4.encode函数5.解压函数#include <stdio.h>#include <string.h>#include <stdlib.h>#include <conio.h>#include <time.h>struct node{long weight; //权值unsigned char ch;//字符int parent,lchild,rchild;char code[256];//编码的位数最多为256位int CodeLength;//编码长度}hfmnode[512];void compress();void uncompress();//主函数void main(){int choice;printf("请选择1~3:\n");printf("1.压缩文件\n");printf("2.解压文件\n");printf("3.退出!\n");scanf("%d",&choice);if(choice==1)compress();else if(choice==2)uncompress();else if(choice==3)return;else printf("输入错误!"); }//压缩函数void compress(){int i,j;char infile[20],outfile[20];FILE *ifp,*ofp;unsigned char c;//long FileLength,filelength=0;int n,m;//叶子数和结点数int s1,s2; //权值最小的两个结点的标号char codes[256];long sumlength=0;float rate,speed;int count=0;clock_t start1, start2,finish1,finish2;double duration1,duration2;void encode(struct node *nodep,int n);//编码函数int select(struct node *nodep,int pose);//用于建哈弗曼树中选择权值最小的结点的函数printf("请输入要压缩的文件名:");scanf("%s",infile);ifp=fopen(infile,"rb");if(ifp==NULL){printf("文件名输入错误,文件不存在!\n");return;}printf("请输入目标文件名:");scanf("%s",outfile);ofp=fopen(outfile,"wb");if(ofp==NULL){printf("文件名输入错误,文件不存在!\n");return;}start1=clock() ;//开始计时1//统计文件中字符的种类以及各类字符的个数//先用字符的ASCII码值代替结点下标FileLength=0;while(!feof(ifp)){fread(&c,1,1,ifp);hfmnode[c].weight++;FileLength++;}FileLength--; //文件中最后一个字符的个数会多统计一次,所以要减一hfmnode[c].weight--;//再将ASCII转换为字符存入到结点的ch成员里,同时给双亲、孩子赋初值-1n=0;for(i=0;i<256;i++)if(hfmnode[i].weight!=0){hfmnode[i].ch=(unsigned char)i;n++;//叶子数hfmnode[i].lchild=hfmnode[i].rchild=hfmnode[i].parent=-1;}m=2*n-1;//哈弗曼树结点总数j=0;for(i=0;i<256;i++)//去掉权值为0的结点if(hfmnode[i].weight!=0){hfmnode[j]=hfmnode[i];j++;}for(i=n;i<m;i++)//初始化根结点{hfmnode[i].lchild=hfmnode[i].rchild=-1;hfmnode[i].parent=-1;}//建立哈弗曼树for(i=n;i<m;i++){s1=select(hfmnode,i-1);hfmnode[i].lchild=s1;hfmnode[s1].parent=i;s2=select(hfmnode,i-1);hfmnode[i].rchild=s2;hfmnode[s2].parent=i;hfmnode[i].weight=hfmnode[s1].weight+hfmnode[s2].weight;}//编码encode(hfmnode,n);finish1=clock();duration1=(double)(finish1- start1) / CLOCKS_PER_SEC;/*printf( "哈弗曼树编码用时为:%f seconds\n", duration1 );*/printf("编码完成,是否查看编码信息: y or n?\n");c=getch();if(c=='y'){ printf("\n");printf("叶子数为%d,结点数为%d\n",n,m);for(i=0;i<n;i++)printf("%d号叶子结点的权值为:%ld,双亲为:%d,左右孩子:%d,编码为:%s\n",i,hfmnode[i].weight,hfmnode[i].parent,hfmnode[i].lchild,hfmnode[i].code) ;}start2=clock() ;//开始计时2fseek(ifp,0,SEEK_SET);//将ifp指针移到文件开头位置fwrite(&FileLength,4,1,ofp);//将FileLength写入目标文件的前4个字节的位置fseek(ofp,8,SEEK_SET);//再将目标文件指针ofp移到距文件开头8个字节位置codes[0]=0;//将编码信息写入目标文件while(!feof(ifp)){fread(&c,1,1,ifp);filelength++;for(i=0;i<n;i++)if(c==hfmnode[i].ch) break; //ch必须也为unsigned 型strcat(codes,hfmnode[i].code);while(strlen(codes)>=8){for(i=0;i<8;i++)//将codes的前8位01代码表示的字符存入c{if(codes[i]=='1')c=(c<<1)|1;else c=c<<1;}fwrite(&c,1,1,ofp); //将新的字符写入目标文件sumlength++;strcpy(codes,codes+8);//更新codes的值}if(filelength==FileLength) break;}//再将剩余的不足8位的01代码补全8位,继续写入if(strlen(codes)>0){strcat(codes,"00000000");for(i=0;i<8;i++){if(codes[i]=='1')c=(c<<1)|1;else c=c<<1;}fwrite(&c,1,1,ofp);sumlength++;}sumlength+=8;printf("编码区总长为:%ld个字节\n",sumlength-8);//将sumlength和n的值写入目标文件,为的是方便解压fseek(ofp,4,SEEK_SET);fwrite(&sumlength,4,1,ofp);//把sumlength写进目标文件的第5-8个字节里fseek(ofp,sumlength,SEEK_SET);fwrite(&n,4,1,ofp);//把叶子数n写进编码段后面的4个字节的位置//为方便解压,把编码信息存入n后面的位置//存储方式为:n*(字符值(1个字节)+该字符的01编码的位数(1个字节)+编码(字节数不确定,用count来计算总值))for(i=0;i<n;i++){fwrite(&(hfmnode[i].ch),1,1,ofp);c=hfmnode[i].CodeLength;//编码最长为256位,因此只需用一个字节存储fwrite(&c,1,1,ofp);//写入字符的编码if(hfmnode[i].CodeLength%8!=0)for(j=hfmnode[i].CodeLength%8;j<8;j++)//把编码不足8位的在低位补0,赋值给C,再把C写入strcat(hfmnode[i].code,"0");while(hfmnode[i].code[0]!=0)//开始存入编码,每8位二进制数存入一个字节{c=0;for(j=0;j<8;j++){if(hfmnode[i].code[j]=='1')c=(c<<1)|1;else c=c<<1;}strcpy(hfmnode[i].code,hfmnode[i].code+8);//编码前移8位,继续存入编码count++; //编码占的字节数的总值fwrite(&c,1,1,ofp);}}printf("\n");finish2=clock();duration2=(double)(finish2- start2) / CLOCKS_PER_SEC;/*printf( "写入目标文件用时为:%f seconds\n", duration2);*/printf( "压缩用时为:%f seconds\n", duration1+duration2);speed=(float)FileLength/(duration1+duration2)/1000;printf("\n压缩速率为:%5.2f KB/S\n",speed);printf("\n");printf("源文件长度为:%ld个字节\n",FileLength);sumlength=sumlength+4+n*2+count; //计算压缩后文件的长度printf("压缩后文件长度为:%ld个字节\n",sumlength);rate=(float)sumlength/(float)FileLength;printf("压缩率(百分比)为:%4.2f%%%\n",rate*100);fclose(ifp);fclose(ofp);return;}//返回书签//建立哈弗曼树中用于选择最小权值结点的函数int select(struct node *nodep,int pose){int i;int s1;long min=2147483647;//s初值为long型的最大值for(i=0;i<=pose;i++){if(nodep[i].parent!=-1)continue;if(nodep[i].weight<min){min=nodep[i].weight;s1=i;}}return s1;}//返回书签//哈弗曼编码函数void encode(struct node *nodep,int n){ //从叶子向根求每个字符的哈弗曼编码int start;int i,f,c;char codes[256];codes[n-1]='\0'; //编码结束符for(i=0;i<n;i++) //逐个字符求哈弗曼编码{start=n-1;for(c=i,f=nodep[i].parent;f!=-1;c=f,f=nodep[f].parent){start--;if(nodep[f].lchild==c)codes[start]='0';else codes[start]='1';}strcpy(nodep[i].code,&codes[start]);nodep[i].CodeLength=strlen(nodep[i].code);}}//返回书签//解压函数void uncompress() //解压文件{clock_t start, finish;double duration;FILE *ifp,*ofp;char infile[20],outfile[20];long FileLength,sumlength,filelength;int n,m;int i,j,k;char buf[256],codes[256];unsigned char c;int maxlength;float speed;printf("请输入要解压的文件名:");scanf("%s",infile);ifp=fopen(infile,"rb");if(ifp==NULL){printf("文件名输入错误,文件不存在!\n");return;}printf("请输入目标文件名:");scanf("%s",outfile);ofp=fopen(outfile,"wb");if(ofp==NULL){printf("文件名输入错误,文件不存在!\n");return;}start=clock() ;//开始计时fread(&FileLength,4,1,ifp);//从压缩文件读出FileLength、sumlengthfread(&sumlength,4,1,ifp);fseek(ifp,sumlength,SEEK_SET); //利用sumlength读出n的值fread(&n,4,1,ifp);printf("\n解码信息:源文件长度为%d个字节,字符种类n=%d\n",FileLength,n);for(i=0;i<n;i++)//读结点信息{fread(&hfmnode[i].ch,1,1,ifp);//字符fread(&c,1,1,ifp);//编码长度hfmnode[i].CodeLength=c;hfmnode[i].code[0]=0;if(hfmnode[i].CodeLength%8>0) m=hfmnode[i].CodeLength/8+1;//m 为编码占的字节数else m=hfmnode[i].CodeLength/8;for(j=0;j<m;j++)//根据字节长度m读出编码{fread(&c,1,1,ifp);//此处c为01编码转换成的字符itoa(c,buf,2);//字符型编码转换成二进制型(首位为1)//如果编码不够8位,则说明缺少了8-k位0,因此应先在前面空缺位写0for(k=8;k>strlen(buf);k--){strcat(hfmnode[i].code,"0");}//再把二进制编码存进hfmnode.code中strcat(hfmnode[i].code,buf);}hfmnode[i].code[hfmnode[i].CodeLength]=0;//去掉编码中多余的0 }//找出编码长度的最大值maxlength=0;for(i=0;i<n;i++)if(hfmnode[i].CodeLength>maxlength)maxlength=hfmnode[i].CodeLength;//开始写入目标文件fseek(ifp,8,SEEK_SET); //指针指向编码区,开始解码filelength=0;codes[0]=0;buf[0]=0;while(1){while(strlen(codes)<maxlength)//codes小于编码长度的最大值时,继续读码{fread(&c,1,1,ifp);itoa(c,buf,2);//还原编码for(k=8;k>strlen(buf);k--){strcat(codes,"0");//把缺掉的0补上}strcat(codes,buf);//codes中此时存的为一串01编码}for(i=0;i<n;i++){ //在codes中查找能使其前weight位和hfmnode.code相同的i值,weight 即为codelengthif(memcmp(hfmnode[i].code,codes,(unsignedint)hfmnode[i].CodeLength)==0) break;}strcpy(codes,codes+hfmnode[i].CodeLength);//更新codes的值c=hfmnode[i].ch;fwrite(&c,1,1,ofp);filelength++;if(filelength==FileLength) break;//写入结束}finish = clock();duration = (double)(finish - start) / CLOCKS_PER_SEC;printf( "\n解压完成,解压用时为:%f seconds\n", duration );fseek(ifp,0,SEEK_SET);FileLength=0;while(!feof(ifp)){fread(&c,1,1,ifp);FileLength++;}FileLength--;speed=(float)FileLength/duration/1000;/*printf("此文件长度为:%ld个字节\n",FileLength);*/printf("\n解压速度为:%5.2fKB/S\n",speed);fclose(ifp);fclose(ofp);return;}2.2程序运行结果:1.对文件”测试.txt”进行压缩,压缩后存储在文件”目标.doc”中,压缩速率为:2055.00KB/S,压缩率为64.92%。