您的位置:首页 > 编程语言

huffman算法编写的压缩软件程序源代码

2015-01-07 14:16 148 查看
转自:/article/3719738.html 点击打开链接

/**

* 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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: