📄 huffman.cpp
字号:
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
int m,s1,s2;
FILE *fp1;
FILE *fp2;
FILE *fp3;
FILE *fp4;
FILE *fp5;
int j=0; long int s=0;int left;
int num[128]={0};char ch=48;
char filename[50];
typedef struct {
char name;
int weight;
int parent,lchild,rchild;
}HTNode,*HuffmanTree; HuffmanTree HT;
typedef struct {
int weight;
char name;
}codeweight; codeweight cw[128];
typedef char **HuffmanCode; HuffmanCode HC;
void Select(HuffmanTree HT,int g,int &s1,int &s2)
{
int j,k,m,n;
for(k=1;k<=g;k++)
{
if(HT[k].parent==0)
{ s1=k; break;}
}
for(j=1;j<=g;j++)
{
if((HT[j].weight<HT[k].weight)&&(HT[j].parent==0))
s1=j;
}
for(m=1;m<=g;m++)
{
if((HT[m].parent==0)&&(m!=s1))
{s2=m;break;}
}
for(n=1;n<=g;n++)
if((HT[n].weight<HT[m].weight)&&(HT[n].parent==0)&&(n!=s1)) s2=n;
}
//编码
void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, codeweight *cw, int n)
{
int i,m,s1=0,s2=0;
int c,f,start;
char *cd;
if (n<=1) return;
m = 2 * n - 1;
HT = (HuffmanTree)malloc((m+1) * sizeof(HTNode));
for (i=1; i<=n; i++)
{
HT[i].weight=cw[i-1].weight;
HT[i].name=cw[i-1].name;
HT[i].parent=0;
HT[i].lchild=0;
HT[i].rchild=0;
}
for (i=n+1; i<=m; i++)
{
HT[i].weight=0;
HT[i].parent=0;
HT[i].lchild=0;
HT[i].rchild=0;
}
for (i=n+1; i<=m; i++)
{
Select(HT, i-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;
}
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);
}
//******************译码*****************************//
void HuffmanTran(HuffmanTree &HT,FILE *fp4,FILE *fp5,int n)
{
HuffmanTree p=HT+2*n-1;
char ch=48;
while(1)
{
ch=fgetc(fp4);
if(ch==EOF)break;
if(ch=='0') p=HT+p->lchild;
else if(ch=='1') p=HT+p->rchild;
if(p->lchild==0&&p->rchild==0)
{
//共n个权值中查找weigt的对应码
fprintf(fp5,"%c",p->name);
p=HT+2*n-1;
}
}
fclose(fp4);
fclose(fp5);
}
//-----函数---------
//统计源文件字符
void statistics_file () {
printf("请输入要译码的文件名(例如e:\\source.txt)");
scanf("%s",filename);
if( (fp1=fopen(filename,"r"))==NULL )
{
printf("open source.txt fail!");
exit(0);
}
if( (fp2=fopen("e:\\statistics.txt","w+"))==NULL )
{
printf("create statistics.txt fail!");
fclose(fp1);
exit(0);
}
//---建树并输出赫夫曼编码
while(1)
{
ch=fgetc(fp1);
if(ch==EOF){fseek(fp1,0,0);break;}
++num[ch];
}
for(int i=0;i<128;i++)
{
if(num[i])
{
fprintf(fp2,"%c %d\n",i,num[i]);
cw[j].name=i;cw[j].weight=num[i];
++j;
}
}
fclose(fp2);
}
void create_code() {
HuffmanCoding(HT,HC,cw,j);
if((fp3=fopen("e:\\code.txt","w+"))==NULL )
{
printf("create code.txt fail!");
exit(0);
}
for(int i=1;i <= j;i++)
fprintf(fp3,"%c %s\n",cw[i-1].name,HC[i]);
fclose(fp3);
}//二进制压缩编码输出
void bin_code (){
fp4=fopen("e:\\source_code.txt","w+");
ch=48;
while(1)
{
ch=fgetc(fp1);
if(ch==EOF)break;
for(int i=0;i<j;i++)
if(ch==cw[i].name)fputs(HC[i+1],fp4);
}
fclose(fp1);
fclose(fp4);
fp1=fopen("e:\\bin_code","wb+");
fp4=fopen("e:\\source_code.txt","rb");
char bin=0; char c;
int t,x;
for(t=0;t<8;t++)
{
ch=fgetc(fp4);
if(ch==EOF)
{
for(left=0;left<t;left++)
if((bin&(1<<(7-left)))==0){c='0';fputc(c,fp1);}
else {c='1';fputc(c,fp1);}
}
if(ch==EOF)break;
if(ch==48)x=0;else x=1;
bin=bin|x<<(7-t);
++s;
if(t==7){t=-1;fwrite(&bin,sizeof(char),1,fp1);bin=0; }
}
fclose(fp1);
fclose(fp4);
}//二进制编码的译码输出
void tran_code(){
unsigned char a;
fp1=fopen("e:\\bin_code","rb");
fp4=fopen("e:\\pre2_code.txt","wb+");
for(int i=0;i<s/8;i++)
{
fread(&a,sizeof(char),1,fp1);
for(int t=0;t<8;t++)
if((a&(1<<(7-t)))==0){ch='0';fputc(ch,fp4);}
else {ch='1';fputc(ch,fp4);}
}
for(int t=0;t<left;t++)
fputc(fgetc(fp1),fp4);
fclose(fp1);
fclose(fp4);
fp4=fopen("e:\\pre2_code.txt","rb");
fp5=fopen("e:\\tran_code.txt","wb+");
HuffmanTran(HT,fp4,fp5,j);
}
void main()
{
unsigned char choice;
printf("***********哈夫曼编译码系统**********\n\n");
printf("操作提示:\n");
printf(" 统计字符权值:<S>\n");
printf(" 字符编码输出:<C>\n");
printf(" 文件编码输出:<E>\n");
printf(" 文件译码输出:<D>\n");
printf(" 退出应用系统:<Q>\n");
while(choice!='Q')
{
printf("\n请选择相应的操作:(生成文件默认保存在E:\)");
scanf("%c",&choice);
if (choice==10)scanf("%c",&choice);
switch (choice)
{
case 'S':
{ statistics_file ();printf("\n生成字符统计文件statistics.txt\n");}break;
case 'C':
{ create_code(); printf("\n生成字符编码文件code.txt\n");}break;
case 'E':
{ bin_code();printf("\n生成文件编码文件source_code.txt二进制压缩编码文件bin_code\n"); }break;
case 'D':
{ tran_code();printf("\n生成文件译码文件tran_code.txt\n");}break;
case 'Q':
break;
default :
printf("输入有误,请重新选择!\n");
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -