huffman 树的压缩和解压缩.docx
- 文档编号:5902073
- 上传时间:2023-01-02
- 格式:DOCX
- 页数:21
- 大小:20.24KB
huffman 树的压缩和解压缩.docx
《huffman 树的压缩和解压缩.docx》由会员分享,可在线阅读,更多相关《huffman 树的压缩和解压缩.docx(21页珍藏版)》请在冰豆网上搜索。
huffman树的压缩和解压缩
//huff.h
#pragmaonce
#include"list.h"
#defineLEAF_NUM256//0~255ASCII表中的有效字符
#defineUNLEAF_NUM(LEAF_NUM-1)//中间结点是叶子结点-1
#defineALL_NUM(LEAF_NUM+UNLEAF_NUM)
//0~510
#defineUNUSEDALL_NUM//511
typedefunsignedshortuint16_t;
typedefuint16_telem_t;
structhuff_tree{
uint16_tparent;
uint16_tlchild;
uint16_trchild;
};
structhuff_node{
structlist_headlist;
structhuff_treetree;
size_tweight;//频率次数
unsignedshortcode;
unsignedcharcode_len;
};
//table['a']=
#defineHUFF_MAGIC0x88888888
structhuff_head{
unsignedintmagic;//魔术字用来验证
uint16_ttype;//zip:
0x11rar:
0x22hz:
0x33
uint16_troot;
size_tfile_size;
structhuff_nodetable[0];
};
structhuff_info{
structhuff_nodetable[ALL_NUM];//编码表
FILE*pfsrc;
FILE*pfdst;
structlist_headhead;
uint16_troot;
size_tfile_size;
int(*compress)(structhuff_info*info,constchar*src,constchar*zip);
int(*decompress)(structhuff_info*info,constchar*zip,constchar*orig);
};
inthuff_init(structhuff_info*info);
inthuff_destroy(structhuff_info*info);
#defineWEIGHT(i)(info->table[i].weight)
#defineCODE(i)(info->table[i].code)
#defineCODE_LEN(i)(info->table[i].code_len)
#defineLIST(i)(info->table[i].list)
#defineTREE(i)(info->table[i].tree)
#definePARENT(i)(info->table[i].tree.parent)
#defineLCHILD(i)(info->table[i].tree.lchild)
#defineRCHILD(i)(info->table[i].tree.rchild)
staticinlinevoidhf_tree_node_init(structhuff_tree*node)
{
node->parent=UNUSED;
node->lchild=UNUSED;
node->rchild=UNUSED;
}
//huff.c
#include
#include
#include
#include
#include"huff.h"
staticinlinevoidhf_tree_node_init(structhuff_tree*node)
{
node->parent=UNUSED;
node->lchild=UNUSED;
node->rchild=UNUSED;
}
staticinthf_statistic_weight(structhuff_info*info)
{
unsignedcharrbuf=0;
size_tn=0;
while((n=fread(&rbuf,1,1,info->pfsrc))!
=0){
WEIGHT(rbuf)+=1;
}
#ifdefDEBUG
{
for(n=0;n if(WEIGHT(n)! =0){ printf("'%c'=%u\n",(unsignedchar)n,WEIGHT(n)); } } } #endif return0; } staticintlist_node_cmp(conststructlist_head*a,conststructlist_head*b) { structhuff_node*pa=list_entry(a,structhuff_node,list); structhuff_node*pb=list_entry(b,structhuff_node,list); returnpa->weight-pb->weight; } voidinsert_sort(structlist_head*head,int(*cmp)(conststructlist_head*,conststructlist_head*)); staticinthf_build_sort_list(structhuff_info*info) { size_ti; for(i=0;i if(WEIGHT(i)! =0) list_add_tail(&info->head,&LIST(i)); } #ifdefDEBUG { printf("beforesort-----\n"); structhuff_node*pa=NULL; list_for_each_entry(pa,&info->head,list){ size_tn=pa-info->table; printf("tab[%u]: '%c': %u\n",n,(unsignedchar)n,WEIGHT(n)); } } #endif insert_sort(&info->head,list_node_cmp); #ifdefDEBUG { printf("aftersort-------\n"); structhuff_node*pa=NULL; list_for_each_entry(pa,&info->head,list){ size_tn=pa-info->table; printf("tab[%u]: '%c': %u\n",n,(unsignedchar)n,WEIGHT(n)); } } #endif return0; } staticvoidlist_add_with_sort(structlist_head*head,structlist_head*node) { structlist_head*cur=NULL; for(cur=head->next;cur! =head;cur=cur->next){ if(list_node_cmp(node,cur)>0){ continue; }else{ break; } } __list_add(node,cur->prev,cur); } staticinthf_build_hufftree(structhuff_info*info) { uint16_tindex=LEAF_NUM;//256 //1.循环直到链表中只剩下一个结点 while(info->head.next->next! =&info->head){ //2.选出权值最小的两个结点 structlist_head*a=info->head.next; structlist_head*b=a->next; structhuff_node*pa=list_entry(a,structhuff_node,list); structhuff_node*pb=list_entry(b,structhuff_node,list); uint16_tpan=pa-info->table; uint16_tpbn=pb-info->table; //3.创建一个中间结点,其权值是前两者之和 WEIGHT(index)=pa->weight+pb->weight; LCHILD(index)=pan; RCHILD(index)=pbn; PARENT(pan)=index; PARENT(pbn)=index; #ifdefDEBUG { printf("table[%hu](%u)=table[%hu](%u)+table[%hu](%u)\n", index,WEIGHT(index),pan,WEIGHT(pan),pbn,WEIGHT(pbn)); } #endif //4.删除前两个结点,将中间结点添加到有序序列中 list_del_init(a); list_del_init(b); list_add_with_sort(&info->head,&LIST(index)); ++index; } //5.指定根结点: index之前因为++index多加一次 if(index! =256){ info->root=index-1; }else{ info->root=256; } #ifdefDEBUG { printf("info->root: %hu\n",info->root); } #endif return0; } staticinthf_fill_code(structhuff_info*info) { uint16_tcur=UNUSED; uint16_ti; for(i=0;i if(WEIGHT(i)==0){ continue; } cur=i; while(cur! =info->root){ CODE(i)<<=1; if(RCHILD(PARENT(cur))==cur){ CODE(i)|=1; } cur=PARENT(cur); CODE_LEN(i)+=1; } #ifdefDEBUG { printf("table[%hu]('%c'): %x\n",i,(unsignedchar)i,CODE(i)); } #endif } return0; } staticinthuff_prepare(structhuff_info*info) { assert(info! =NULL); //1.遍历文件,统计出现的频率 if(hf_statistic_weight(info)<0){ printf("hf_statistic_weightfailed\n"); return-1; } //2.构建有序序列(按照权值从小到大排列) if(hf_build_sort_list(info)<0){ printf("hf_build_sort_listfailed\n"); return-2; } //3.构建最优二叉树 if(hf_build_hufftree(info)<0){ printf("hf_build_huff_treefailed\n"); return-3; } //4.填充编码 if(hf_fill_code(info)<0){ printf("hf_fill_codefailed\n"); return-4; } return0; } staticinthf_make_huff_head(structhuff_info*info) { size_thead_size=sizeof(structhuff_head)+sizeof(structhuff_node)*(info->root+1); structhuff_head*phf_head=(structhuff_head*) malloc(head_size); assert(phf_head! =NULL); phf_head->magic=HUFF_MAGIC; phf_head->type=0x33;//HZ0x33 //将文件流置到文件结尾 fseek(info->pfsrc,0,SEEK_END); //获取原文件大小 phf_head->file_size=ftell(info->pfsrc); phf_head->root=info->root; memcpy(phf_head->table,info->table,sizeof(structhuff_node)*(info->root+1)); fseek(info->pfdst,0,SEEK_SET); fwrite(phf_head,head_size,1,info->pfdst); #ifdefDEBUG { printf("magic: %x\n",phf_head->magic); printf("type: %x\n",phf_head->type); printf("file_size: %u\n",phf_head->file_size); printf("head_size: %u\n",head_size); printf("root: %hu\n",phf_head->root); } #endif free(phf_head); return0; } staticinthuff_compress(structhuff_info*info,constchar*src,constchar*dst) { unsignedcharrbuf=0; unsignedcharwbuf=0; uint16_ti; uint16_tcount=0; assert(info! =NULL); if(src==NULL){ info->pfsrc=stdin; }else{ info->pfsrc=fopen(src,"r"); if(info->pfsrc==NULL){ printf("fopen\"%s\"failed\n",src); } } if(dst==NULL){ info->pfdst=stdout; setbuf(stdout,NULL);//关闭标准输出的缓冲功能 }else{ info->pfdst=fopen(dst,"w"); if(info->pfdst==NULL){ printf("fopen\"%s\"failed\n",src); } } if(huff_prepare(info)<0){ printf("huff_preparefailed\n"); return-1; } //1.写入huff头部信息 if(hf_make_huff_head(info)<0){ printf("make_huff_headfailed\n"); return-2; } //2.再次遍历文件,根据编码表写入目标文件 rewind(info->pfsrc); while(fread(&rbuf,1,1,info->pfsrc)! =0){ for(i=0;i wbuf<<=1; wbuf|=(CODE(rbuf)>>i)&1; ++count; if(count==8){ fwrite(&wbuf,1,1,info->pfdst); #ifdefDEBUG { printf("%x",(unsignedchar)wbuf); fflush(stdout); } #endif wbuf=0; count=0; } } } //将未完成wbuf部分写入目标文件 if(count! =0){ wbuf<<=8-count; fwrite(&wbuf,1,1,info->pfdst); #ifdefDEBUG printf("%x\n",wbuf); #endif } return0; } staticinthf_unpack_huff_head(structhuff_info*info) { structhuff_head*phf_head=(structhuff_head*)malloc(sizeof(*phf_head)); assert(phf_head! =NULL); fread(phf_head,sizeof(*phf_head),1,info->pfsrc); #ifdef_DEBUG { printf("magic: %x\n",phf_head->magic); printf("type: %x\n",phf_head->type); printf("file_size: %u\n",phf_head->file_size); printf("root: %hu\n",phf_head->root); } #endif info->root=phf_head->root; info->file_size=phf_head->file_size; //size_ttable_size=sizeof(structhuff_node)*(info->root+1); //验证魔术字 if(phf_head->magic! =HUFF_MAGIC){ printf("文件损坏,请重试\n"); return-1; } fread(info->table,sizeof(structhuff_node),info->root+1,info->pfsrc); #ifdef_DEBUG printf("head_size: %lu\n",ftell(info->pfsrc)); #endif free(phf_head); return0; } staticinthuff_decompress(structhuff_info*info,constchar*src,constchar*dst) { assert(info! =NULL); if(src==NULL){ info->pfsrc=stdin; }else{ info->pfsrc=fopen(src,"r"); if(info->pfsrc==NULL){ printf("fopen\"%s\"failed\n",src); } } if(dst==NULL){ info->pfdst=stdout; setbuf(stdout,NULL);//关闭标准输出的缓冲功能 }else{ info->pfdst=fopen(dst,"w"); if(info->pfdst==NULL){ printf("fopen\"%s\"failed\n",src); } } //1.解开压缩包的头部信息 if(hf_unpack_huff_head(info)<0){ printf("hf_unpack_huff_headfailed"); return-1; } //2.根据编码表将编码转化字符 uint16_tcur; uint16_ti; unsignedcharrbuf; volatilesize_tfile_size=0; cur=info->root; while(fread(&rbuf,1,1,info->pfsrc)! =0){ for(i=0;i<8;++i){ if((rbuf>>(7-i))&1){ cur=RCHILD(cur); }else{ cur=LCHILD(cur); } //直到叶子节点为有效数据,写入目标文件 if(cur fwrite(&cur,1,1,info->pfdst); cur=info->root; if(++file_size==info->file_size){ gotoout; } } } } out: return0; } inth
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- huffman 树的压缩和解压缩 压缩 和解
![提示](https://static.bdocx.com/images/bang_tan.gif)