转自:http://blog.csdn.net/gubojun123/article/details/8286156 点击打开链接
- /**
- * author:gubojun
- * time:2012-12-11
- * name:~
- * version:0.1
- */
- #include<stdio.h>
- #include<stdlib.h>
- #include<string.h>
- /**
- * Huffman树的结构体
- */
- typedef struct node{
- char byte;//记录字符
- int weight;//权值
- char bit[10];//编码值
- struct node *lchild,*rchild,*next;
- }hufnode,*huflink;
- huflink codetree;
- //--------------------编码对照表
- char codelist[256][10];int nn;
- //---------------------------------------------------------------------------------
- /**
- * name:comp
- * author:gubojun
- * time:2012-12-11
- * in:两个节点的地址
- * out:int 大小
- * function:qsort比较函数,降序排列结构体数组
- */
- int comp(const void *a,const void *b){
- return (*(huflink)b).weight-(*(huflink)a).weight;
- }
- //---------------------------------------------------------------------------------
- /**
- * 函数功能:将新结点s插入到有序链表root中,并保持链表的有序性
- * 函数参数:链表头结点指针root;结点指针s
- */
- huflink insert(huflink root,huflink s){
- huflink p1,p2;
- if(root==NULL)root=s;
- else{
- p1=NULL;
- p2=root;
- while(p2 && p2->weight < s->weight){/*查找插入位置*/
- p1=p2;
- p2=p2->next;
- }
- s->next=p2;
- if(p1==NULL) root=s;
- else p1->next=s;
- }
- return root;
- }
- //---------------------------------------------------------------------------------
- /**
- * 函数功能:根据有序链表root建立huffman树
- * 函数参数:链表头结点二级指针变量root
- */
- void creathuffman(huflink *root){//二阶指针(地址的指针)
- huflink s,rl,rr;
- while(*root && (*root)->next){//*root表示一个地址
- rl=*root;
- rr=(*root)->next;
- *root=rr->next;
- s=(huflink)malloc(sizeof(hufnode));/*生成新结点*/
- s->next=NULL;
- s->weight=rl->weight+rr->weight;
- s->lchild=rl;
- s->rchild=rr;
- rl->next=rr->next=NULL;
- s->bit[0]='\0';
- *root=insert(*root,s);/*将新结点插入到有序表root中*/
- }
- }
- void inorder(huflink t){ /*中序遍历二叉树*/
- if(t){
- inorder(t->lchild);
- printf("%4d",t->weight);
- inorder(t->rchild);
- }
- }
- void preorder(huflink t){ /*前序遍历二叉树*/
- if(t){
- printf("%4d",t->weight);
- preorder(t->lchild);
- preorder(t->rchild);
- }
- }
- void levelorder(huflink t){ //层次遍历二叉树
- huflink queue[256]; //存放等待访问的节点队列
- int f,r,i=0; //f,r分别为对头、队尾指针
- int length;
- huflink p;
- f=0;r=1;queue[0]=t;
- while(f<r){ //队列不为空
- p=queue[f];f++;
- if(p->lchild==NULL && p->rchild==NULL){
- printf("%c",p->byte);
- strcpy(codelist[p->byte],p->bit);
- printf("(%5s) ",codelist[p->byte]);
- }
- if(p->lchild){
- queue[r]=p->lchild;
- strcpy((p->lchild)->bit,p->bit);
- strcat((p->lchild)->bit,"0");
- r++;
- }
- if(p->rchild){
- queue[r]=p->rchild;
- strcpy((p->rchild)->bit,p->bit);
- strcat((p->rchild)->bit,"1");
- r++;
- }
- }
- }
- //---------------------------------------------------------------------------------
- /**
- * name:compress
- * author:gubojun
- * time:2012-12-11
- * in:char[],char[],输入的文件名,输出的文件名
- * out:none
- */
- void compress(char infilename[],char outfilename[]){
- long flength=0; //记录压缩前文件长度
- char ch,bin[10]; //存储读入的字符
- huflink s,p;
- hufnode list[256];
- int i,j,word,count;
- FILE *f_in,*f_out;
- //----------------------判断文件是否打开成功
- if((f_in=fopen(infilename,"r"))==NULL){
- printf("Failure to open %s\n",infilename);
- return;
- }
- //----------------------初始化数组
- for(i=0;i<256;i++){
- list[i].byte=i; //初始化字符
- list[i].weight=0; //初始化权重
- }
- //----------------------统计权值大小
- while((ch=fgetc(f_in))!=EOF){
- list[ch].weight++; //权值加1
- putchar(ch); //输出字符
- flength++; //长度加1
- }
- nn=flength;
- //----------------------关闭文件
- fclose(f_in);
- //----------------------结构体数组快排
- qsort(list,256,sizeof(hufnode),comp);
- printf("\nlength:%d\n\n",flength); //输入后换行
- //----------------------建立Huffman编码树
- codetree=(huflink)malloc(sizeof(hufnode));
- codetree->byte=list[0].byte;//初始化字符
- codetree->weight=list[0].weight;//初始化权重
- codetree->lchild=codetree->rchild=codetree->next=NULL;
- codetree->bit[0]='\0';
- i=0;
- while(list[++i].weight){//当权重不为0时
- s=(huflink)malloc(sizeof(hufnode));
- s->byte=list[i].byte;
- s->weight=list[i].weight;
- s->lchild=s->rchild=NULL;//左右孩子节点赋值为0
- s->bit[0]='\0';
- s->next=codetree;
- codetree=s;
- }
- //----------------------打印权值和字符
- p=codetree;
- while(p){
- printf("%d (%c) ",p->weight,p->byte);
- p=p->next;
- }
- printf("\n");
- //----------------------建立编码树
- creathuffman(&codetree);
- //----------------------根据编码树编码
- //----------------------层次遍历编码树填写编码对照表
- levelorder(codetree);
- //----------------------判断文件是否打开成功
- if((f_in=fopen(infilename,"r"))==NULL){
- printf("Failure to open %s\n",infilename);
- return;
- }
- //----------------------判断文件是否打开成功
- if((f_out=fopen(outfilename,"w"))==NULL){
- printf("Failure to open %s\n",outfilename);
- return;
- }
- /*//---------------------写入编码1
- while((ch=fgetc(f_in))!=EOF){
- fprintf(f_out,"%s",codelist[ch]);
- }
- fclose(f_in);fclose(f_out);*/
- printf("\n");
- //----------------------写入编码
- count=i=word=bin[0]=0;
- while((ch=fgetc(f_in))!=EOF){
- count+=strlen(codelist[ch]);
- j=i;
- while(i<count&&i<8){
- word=word+((codelist[ch][i-j]-48)<<(7-i));
- i++;
- }
- if(i==8){
- if(count==8){
- count-=8;i=0;
- fprintf(f_out,"%c",word);
- printf("%d\n",word);
- word=0;
- }
- else{
- count-=8;i=0;
- fprintf(f_out,"%c",word);
- printf("%d\n",word);
- while(i<count&&i<8){
- word=(codelist[ch][i]-48)<<(7-i);
- i++;
- }
- }
- }
- //fprintf(f_out,"%s",codelist[ch]);
- }
- if(i!=8){
- fprintf(f_out,"%c",word);
- printf("%d\n",word);
- }
- fclose(f_in);fclose(f_out);
- }
- //---------------------------------------------------------------------------------
- /**
- * name:uncompress
- * author:gubojun
- * time:2012-12-11
- * in:char[],char[],输入的文件名,输出的文件名
- * out:none
- */
- void uncompress(char infilename[],char outfilename[]){
- FILE *f_in,*f_out;
- char ch;//存储读入的字符
- huflink s,p;
- int i;
- //-----------------------判断文件是否打开成功
- if((f_in=fopen(infilename,"r"))==NULL){
- printf("Failure to open %s\n",infilename);
- return;
- }
- //-----------------------判断文件是否打开成功
- if((f_out=fopen(outfilename,"w"))==NULL){
- printf("Failure to open %s\n",outfilename);
- return;
- }
- /*//------------------------读入编码1
- p=codetree;
- while((ch=fgetc(f_in))!=EOF){
- if(ch=='0'){
- p=p->lchild;
- }
- else{
- p=p->rchild;
- }
- if(p->lchild==NULL && p->rchild==NULL){
- fprintf(f_out,"%c",p->byte);
- p=codetree;
- }
- }*/
- //------------------------读入编码
- printf("\n");
- p=codetree;
- while(fscanf(f_in,"%c",&ch)!=EOF){
- for(i=7;i>=0&&nn;i--){
- if(((ch>>i)&1)==0){
- p=p->lchild;
- }
- else{
- p=p->rchild;
- }
- if(p->lchild==NULL && p->rchild==NULL){
- printf("%c",p->byte);
- fprintf(f_out,"%c",p->byte);
- p=codetree;
- //nn--;
- }
- }
- }
- fclose(f_in);fclose(f_out);
- }
- /************************************************************************
- * name:main
- * author:gubojun
- * time:2012-12-11
- * in:none
- * out:none
- * function:程序的主函数
- ************************************************************************/
- int main(){
- char infilename[256]="in.txt",outfilename[256]="out.txt";
- int choice=1;
- //printf("please input filename:");
- //scanf("%d",infilename);
- //printf("please input filename:");
- //scanf("%d",outfilename);
- printf("1.compress 2uncompress:\n");
- //scanf("%d",&choice);
- switch(choice){
- case 1:compress(infilename,outfilename);
- //break;
- case 2:uncompress(outfilename,"解压后.txt");
- break;
- }
- }
-
源码下载地址:http://download.csdn.net/detail/gubojun123/4876722