文档库 最新最全的文档下载
当前位置:文档库 › 哈夫曼树编码与解码

哈夫曼树编码与解码

#include
#include
#include
#include
#include

typedef struct{
char node;
int weight;
int parent,lchild,rchild;
}HTNode,*HuffmanTree;//动态分配数组存储哈夫曼树

typedef struct{
char node;
int weight;
char *code;
}Code,*HuffmanCode;//动态分配数组存储哈夫曼编码表

void ChooseMin(HuffmanTree HT,int n,int *s1,int *s2){
//取HT[0..n]中的最小值的下标S1和次小值的下标S2
int i,min1=999,min2=999;
for(i=0;i<=n;i++){
if(HT[i].parent!=-1) continue;
else if(HT[i].weightmin2=min1;
*s2=*s1;
min1=HT[i].weight;
*s1=i;
}
else if(HT[i].weightmin2=HT[i].weight;
*s2=i;
}
}
}

void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int n){
//构造哈夫曼树HT,并求出N个字符的哈夫曼编码HC
int i,m,s1=-1,s2=-1;
if(n<=1) return;
m=2*n-1;
HT=(HuffmanTree)malloc(m*sizeof(HTNode));
for(i=0;iHT[i].node=HC[i].node;
HT[i].weight=HC[i].weight;
HT[i].parent=HT[i].lchild=HT[i].rchild=-1;
}
for(;iHT[i].node='\0';
HT[i].weight=0;
HT[i].parent=HT[i].lchild=HT[i].rchild=-1;
}
for(i=n;i//建哈夫曼树
ChooseMin(HT,i-1,&s1,&s2);//求HT[0..i-1]中parent为-1的最小值S1和次小值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;
}


//从叶子到根逆向求每个字符的哈夫曼编码
char *cd;
int k;
cd=(char*)malloc(n*sizeof(char));
int start,c,f;
cd[n-1]='\0';
for(i=0;istart=n-1;
for(c=i,f=HT[i].parent;f!=-1;c=f,f=HT[f].parent){
if(HT[f].lchild==c) cd[--start]='0';
else cd[--start]='1';
}
k=n-start;
HC[i].code=(char*)malloc(k*sizeof(char));
strcpy(HC[i].code,&cd[start]);
}
}

int GetHowmany(char *p){
//返回字符串p中出现的字符种类数目
int i,j,n=strlen(p),flag,num=0;
for(i=0;iflag=1;
for(j=0;jif(p[i]==p[j]){
flag=0;
break;
}
}
if(flag==1) num++;
}
return num;
}

void Weight(char *input,HuffmanCode &HC){
//对输入的字符串进行处理,求出一共有多少种字符及每个字符出现的次数
int i,j,k;
i=j=k=0;
while(input[i]){
for(k=0;kif(input[i]==HC[k].node){
HC[k].weight++;
break;
}
}
if(k==j){
HC[k].node=input[i];
HC[k].weight=1;
j++;
}
i++;
}
}

void Bianma(HuffmanCode HC,char **bianma,char *input,int n){
//根据编码表对输入的字符串进行编码
int i=0,j;
*bianma=(char*)malloc(sizeof(char));
*bianma[0]=0;
while(input[i]){
for(j=0;jif(HC[j].node==input[i]){
realloc(*bianma,strlen(*bianma)+strlen(HC[j].code)+1);
strcat(*bianma,HC[j].code);
break;
}
}
i++;
}
}

void Yima(char *bianma,char *yima,HuffmanTree HT){
int i,j,k,l,root;
//找到哈夫曼树的

根节点
i=0;
while(HT[i].parent!=-1) {
i=HT[i].parent;}
root=i;
//对应编码依次比较,从根节点开始直到叶子节点,找出对应的编码
j=l=0,k=root;
while(bianma[j]!=0){
while(HT[k].lchild!=-1){
if(bianma[j]=='0') {k=HT[k].lchild;j++;}
else if(bianma[j]=='1') {k=HT[k].rchild;j++;}
}
yima[l]=HT[k].node;
l++;
k=root;
}
yima[l]=0;
}

void BIN_TO_DEC(char *p,char *&c,int &n){
//将以字符串形式表示的二进制码每七位一截转换成十进制
//并以字符型数据存储,最后不足七位的在末尾补零
//n返回最后不足七位的个数
int i,j,k,m,flag,num;
m=strlen(p);
n=fmod(m,7);
if(n==0) flag=0;
else flag=1;
k=m/7+flag;
char *q;
q=(char*)malloc((7*k+1)*sizeof(char));
for(i=0;iq[i]=p[i];
}
for(;i<7*k;i++) q[i]='0';
q[7*k]='\0';
c=(char*)malloc((k+1)*sizeof(char));
for(i=0;inum=0;
for(j=0;j<7;j++){
if(q[7*i+j]=='1') num+=pow(2,6-j);
}
c[i]=num;
}
c[i]='\0';
}

void DEC_TO_BIN(char *p,char *&c,int n){
//将字符串p改写成二进制格式
//以01字符串表示二进制数
int i,j,m,a;
m=strlen(p);
c=(char*)malloc((7*m+1)*sizeof(char));
for(i=0;ifor(j=6;j>=0;j--){
a=pow(2,j);
if(p[i]>=a) {
c[7*i+6-j]='1';
p[i]-=a;
}
else c[7*i+6-j]='0';
}
}
if(n!=0) c[m*7+n-7]='\0';
}

void Filesinput(char **input){
char filename[20];
FILE *fp;
printf("请输入文件名:\n");
scanf("%s",&filename);
getchar();
fp=fopen(filename,"r");//只供读取
if(fp==NULL){//如果失败了
printf("找不到呢T^T");
exit(1);
}//中止程序
int i=0;
while(getc(fp)!=EOF)
i++;
*input=(char*)malloc((i+1)*sizeof(char));
rewind(fp);
fgets(*input,i+1,fp);
fclose(fp);//关闭文件
}

void Filesoutput(char *bianma){
char filename[20];
FILE *fp;
printf("保存压缩结果至:");
scanf("%s",filename);
fp=fopen(filename,"w");
fwrite(bianma,1,strlen(bianma),fp);
fclose(fp);
printf("保存完毕\n");
}

int main(){
int n,i,s;
char *input;
printf("压缩文件:");
Filesinput(&input);
printf("文件内容如下:");
puts(input);
HuffmanCode HC;
n=GetHowmany(input);
HC=(HuffmanCode)malloc(n*sizeof(Code));
Weight(input,HC);
printf("\n该字符串一共含有%d个字符,各字符频数如下:\n",n);
for(i=0;iprintf("%c %d",HC[i].node,HC[i].weight);
printf("\n");
}
HuffmanTree HT;
HuffmanCoding(HT,HC,n);
printf("\n生成的编码表信息如下:\n");
for(i=0;iprintf("%c %s\n",HC[i].node,HC[i].code);
}
char *bianma,*yima;
Bianma(HC,&bianma,input,n);
printf("\n编码后信息如下:");
i=0;
while(bianma[i]){
printf("%c",bianma[i]);
i++;
}
printf("\n");
int nn;
char *c;
BIN_TO_DEC((char*)bianma,c,nn);
F

ilesoutput(c);
float bb;
bb=(float)(strlen(bianma))/((float)(strlen(input))*8);
printf("\n压缩比为%f\n",bb);
//以下为解压操作
printf("\n解压文件:");
char *p;
Filesinput(&p);
DEC_TO_BIN(p,bianma,nn);
yima=(char*)malloc((strlen(input)+1)*sizeof(char));
Yima(bianma,yima,HT);
printf("\n将压缩文件解压后信息如下:");
i=0;
while(yima[i]){
printf("%c",yima[i]);
i++;
}
getchar();
return 0;
}











相关文档