哈夫曼编译码器代码课程设计.docx
《哈夫曼编译码器代码课程设计.docx》由会员分享,可在线阅读,更多相关《哈夫曼编译码器代码课程设计.docx(22页珍藏版)》请在冰豆网上搜索。
![哈夫曼编译码器代码课程设计.docx](https://file1.bdocx.com/fileroot1/2023-1/9/cba4cb77-e5cc-4a22-8c34-b88aa31ff269/cba4cb77-e5cc-4a22-8c34-b88aa31ff2691.gif)
哈夫曼编译码器代码课程设计
哈夫曼编\译码器代码课程设计具体要求描述设计一个利用哈夫曼算法的编码和译码系统,重复地显示并处理以下项目,直到选择退出为止。
【基本要求】1)将权值数据存放在数据文件(文件名为data.txt,位于执行程序的当前目录中)2)分别采用动态和静态存储结构3)初始化:
键盘输入字符集大小n、n个字符和n个权值,建立哈夫曼树;4)编码:
利用建好的哈夫曼树生成哈夫曼编码;5)输出编码;6)设字符集
哈夫曼编\译码器代码课程设计哈夫曼编\译码器代码课程设计具体要求描述
设计一个利用哈夫曼算法的编码和译码系统,重复地显示并处理以下项目,直到选择退出为止。
【基本要求】
1)将权值数据存放在数据文件(文件名为data.txt,位于执行程序的当前目录中)
2)分别采用动态和静态存储结构
3)初始化:
键盘输入字符集大小n、n个字符和n个权值,建立哈夫曼树;
4)编码:
利用建好的哈夫曼树生成哈夫曼编码;
5)输出编码;
6)设字符集及频度如下表:
字符空格ABCDEFGHIJKLM
频度1866413223210321154757153220
字符NOPQRSTUVWXYZ
频度5763151485180238181161
【进一步完成内容】
1)对任意输入的一段字符,统计字符出现的频度,完成哈夫曼编码;
2)译码功能;
3)显示哈夫曼树;
4)界面设计的优化。
哈夫曼编译码器
需求分析:
(1)再通信过程中,为了提高信道利用率,缩短信息传输时间降,低传输成本,需要一编译码器。
(2)此哈夫曼编/译码器应具有编和译的双向功能,即在发送端通过编码系统对传入的数据进行编码,
在接受端将数据译码.将具有这两项功能的编译码器用于双工信道,就可满足双工信道的双向编译功能.
(3)输入某段报文时,系统将自动完成编译输出.
要求:
1:
I:
初始化。
从中端读入字符集大小n,以及n个字符和n各权值,建树,并存于hfmTree中
2:
E:
编码。
利用已建好的树(如不在内存,则从文件hfmTree中读入),对文件ToBeTran中的正文进行编码,
然后将结果存入文件CodeFile.
3:
D:
译码。
利用已建好的树将文件CodeFile中的代码进行译码,结果存入文件TextFile中。
4:
P:
印代码文件CodeFile。
将文件以紧凑格式显示在终端上,每行50个代码。
同时将此字符形式的编码文件写入文件CodePrin中。
5T:
印哈夫曼树。
将已在内存中的树以直观的方式(树或凹入表形式)显示在终端,同时将此字符形式
的哈夫曼树写入文件TreePrin中。
以上是题目要求
#definemax50
structa
{
intweight;
intparent,lchild,rchild;
};
structb
{
charcd[max];
intstart;
};
main()
{
structaht[2*max];
structbhcd[max],d;
inti,j,k,n,c,s1,s2,m1,m2,f;
printf("shurun:
");
scanf("%d",&n);
for(i=1;i<=n;i++)
{
printf("shuruquanzhi:
");
scanf("%d",&ht[i].weight);
ht[i].parent=0;
}
for(;i<=2*n-1;i++)
ht[i].parent=ht[i].lchild=ht[i].rchild=0;
for(i=n+1;i<=2*n-1;i++)
{
m1=m2=30000;
s1=s2=0;
for(k=1;k<=i-1;k++)
{
if(ht[k].parent==0&&ht[k].weight{
m2=m1;
s2=s1;
m1=ht[k].weight;
s1=k;
}
elseif(ht[k].parent==0&&ht[k].weight{
m2=ht[k].weight;
s2=k;
}
}
ht[s1].parent=ht[s2].parent=i;
ht[i].lchild=s1;
ht[i].rchild=s2;
ht[i].weight=ht[s1].weight+ht[s2].weight;
}
for(i=1;i<=n;i++)
{
d.start=n-1;
c=i;
f=ht[i].parent;
while(f)
{
if(ht[f].lchild==c)d.cd[--d.start]='0';
elsed.cd[--d.start]='1';
c=f;
f=ht[f].parent;
}
hcd[i]=d;
}
printf("shuchuhafubianma");
for(i=1;i<=n;i++)
{
printf("%d",ht[i].weight);
for(k=hcd[i].start;kprintf("%c",hcd[i].cd[k]);
printf("");
}
}
程序设计方案2
哈夫曼编/译码器(课程设计)
#include
#include
#include
#include
//typedefintTElemType;
constintUINT_MAX=1000;
typedefstruct
{
intweight;
intparent,lchild,rchild;
}HTNode,*HuffmanTree;
typedefchar**HuffmanCode;
//-----------全局变量-----------------------
HuffmanTreeHT;
HuffmanCodeHC;
int*w,i,j,n;
char*z;
intflag=0;
intnumb=0;
//-----------------求赫夫曼编码-----------------------
intmin(HuffmanTreet,inti)
{//函数voidselect()调用
intj,flag;
intk=UINT_MAX;//取k为不小于可能的值
for(j=1;j<=i;j++)
if(t[j].weightk=t[j].weight,flag=j;
t[flag].parent=1;
returnflag;
}
//--------------------slect函数----------------------
voidselect(HuffmanTreet,inti,int&s1,int&s2)
{//s1为最小的两个值中序号小的那个
intj;
s1=min(t,i);
s2=min(t,i);
if(s1>s2)
{
j=s1;
s1=s2;
s2=j;
}
}
//--------------算法6.12--------------------------
voidHuffmanCoding(HuffmanTree&HT,HuffmanCode&HC,int*w,intn)
{//w存放n个字符的权值(均>0),构造赫夫曼树HT,并求出n个字符的赫夫曼编码HC
intm,i,s1,s2,start;
//unsignedc,f;
intc,f;
HuffmanTreep;
char*cd;
if(n<=1)
return;//检测结点数是否可以构成树
m=2*n-1;
HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));//0号单元未用
for(p=HT+1,i=1;i<=n;++i,++p,++w)
{
p->weight=*w;
p->parent=0;
p->lchild=0;
p->rchild=0;
}
for(;i<=m;++i,++p)
p->parent=0;
for(i=n+1;i<=m;++i)//建赫夫曼树
{//在HT[1~i-1]中选择parent为0且weight最小的两个结点,其序号分别为s1和s2
select(HT,i-1,s1,s2);
HT[s1].parent=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*));
//分配n个字符编码的头指针向量([0]不用)
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));
//为第i个字符编码分配空间
strcpy(HC[i],&cd[start]);//从cd复制编码(串)到HC
}
free(cd);//释放工作空间
}
//--------------初始化赫夫曼链表---------------------------------
voidInitialization()
{
flag=1;
intnum;
intnum2;
cout<<"下面初始化赫夫曼链表"<";
cin>>num;
n=num;
w=(int*)malloc(n*sizeof(int));
z=(char*)malloc(n*sizeof(char));
cout<<"\n请依次输入"<必须以回车结束:
"<charbase[2];
for(i=0;i{
cout<<"第"<
"<gets(base);
*(z+i)=*base;
}
for(i=0;i<=n-1;i++)
{
cout<}
cout<<"\n请依次输入"<必须以回车结束):
"<for(i=0;i<=n-1;i++)
{
cout<";
cin>>num2;
*(w+i)=num2;
}
HuffmanCoding(HT,HC,w,n);
//------------------------打印编码-------------------------------------------
cout<<"字符对应的编码为:
"<for(i=1;i<=n;i++)
{
//cout<<"字符"<<*(z+i-1)<<"的编码";
puts(HC[i]);
}
//--------------------------将赫夫曼编码写入文件------------------------
cout<<"下面将赫夫曼编码写入文件"<FILE*htmTree;
charr[]={'','\0'};
if((htmTree=fopen("htmTree.txt","w"))==NULL)
{
cout<<"cannotopenfile"<return;
}
fputs(z,htmTree);
for(i=0;i{
fprintf(htmTree,"%6d",*(w+i));
fputs(r,htmTree);
}
for(i=1;i<=n;i++)
{
fputs(HC[i],htmTree);
fputs(r,htmTree);
}
fclose(htmTree);
cout<<"已将字符与对应编码写入根目录下文件htmTree.txt中"<}
//---------------------获取报文并写入文件---------------------------------
voidInputCode()
{
//cout<<"请输入你想要编码的字符"<FILE*tobetran;
charstr[100];
if((tobetran=fopen("tobetran.txt","w"))==NULL)
{
cout<<"不能打开文件"<return;
}
cout<<"请输入你想要编码的字符"<gets(str);
fputs(str,tobetran);
cout<<"获取报文成功"<fclose(tobetran);
}
//---------------------编码函数---------------------------------
voidEncoding()
{
cout<<"下面对目录下文件tobetran.txt中的字符进行编码"<FILE*tobetran,*codefile;
if((tobetran=fopen("tobetran.txt","rb"))==NULL)
{
cout<<"不能打开文件"<}
if((codefile=fopen("codefile.txt","wb"))==NULL)
{
cout<<"不能打开文件"<}
char*tran;
i=99;
tran=(char*)malloc(100*sizeof(char));
while(i==99)
{
if(fgets(tran,100,tobetran)==NULL)
{
cout<<"不能打开文件"<break;
}
for(i=0;*(tran+i)!
='\0';i++)
{
for(j=0;j<=n;j++)
{
if(*(z+j-1)==*(tran+i))
{
fputs(HC[j],codefile);
if(j>n)
{
cout<<"字符错误,无法编码!
"<break;
}
}
}
}
}
cout<<"编码工作完成"<fclose(tobetran);
fclose(codefile);
free(tran);
}
//-----------------译码函数---------------------------------
voidDecoding()
{
cout<<"下面对根目录下文件codefile.txt中的字符进行译码"<FILE*codef,*txtfile;
if((txtfile=fopen("\\Textfile.txt","w"))==NULL)
{
cout<<"不能打开文件"<}
//txtfile=fopen("Textfile.txt","w");
if((codef=fopen("codefile.txt","r"))==NULL)
{
cout<<"不能打开文件"<}
//codef=fopen("codefile.txt","r");
char*work,*work2,i2;
inti4=0,i,i3;
unsignedlonglength=10000;
work=(char*)malloc(length*sizeof(char));
fgets(work,length,codef);
work2=(char*)malloc(length*sizeof(char));
i3=2*n-1;
for(i=0;*(work+i)!
='\0';i++)
{
i2=*(work+i);
if(HT[i3].lchild==0)
{
*(work2+i4)=*(z+i3-1);
i4++;
i3=2*n-1;
i--;
}
elseif(i2=='0')i3=HT[i3].lchild;
elseif(i2=='1')i3=HT[i3].rchild;
}
*(work2+i4)='\0';
fputs(work2,txtfile);
cout<<"译码完成"<free(work);
free(work2);
fclose(txtfile);
fclose(codef);
}
//-----------------------打印编码的函数----------------------
voidCode_printing()
{
cout<<"下面打印根目录下文件CodePrin.txt中编码字符"<FILE*CodePrin,*codefile;
if((CodePrin=fopen("CodePrin.txt","w"))==NULL)
{
cout<<"不能打开文件"<return;
}
if((codefile=fopen("codefile.txt","r"))==NULL)
{
cout<<"不能打开文件"<return;
}
char*work3;
work3=(char*)malloc(51*sizeof(char));
do
{
if(fgets(work3,51,codefile)==NULL)
{
cout<<"不能读取文件"<break;
}
fputs(work3,CodePrin);
puts(work3);
}while(strlen(work3)==50);
free(work3);
/*intiNum=2,num=2;
while((num=fscanf(codefile,"%d",iNum))!
=NULL)
{
printf("%d",iNum);
fprintf(CodePrin,"%d",iNum);
}
*/
cout<<"打印工作结束"<fclose(CodePrin);
fclose(codefile);
}
//------------------------打印赫夫曼树的函数-----------------------
voidcoprint(HuffmanTreestart,HuffmanTreeHT)
{
if(start!
=HT)
{
FILE*TreePrint;
if((TreePrint=fopen("TreePrint.txt","a"))==NULL)
{cout<<"创建文件失败"<return;
}
numb++;//该变量为已被声明为全局变量
coprint(HT+start->rchild,HT);
cout<weight<fprintf(TreePrint,"%d\n",start->weight);
coprint(HT+start->lchild,HT);
numb--;
fclose(TreePrint);
}
}
voidTree_printing(HuffmanTreeHT,intw)
{
HuffmanTreep;
p=HT+w;
cout<<"下面打印赫夫曼树"<coprint(p,HT);
cout<<"打印工作结束"<}
//------------------------主函数------------------------------------
voidmain()
{
charchoice;
while(choice!
='q')
{cout<<"\n******************************"<cout<<"欢迎使用赫夫曼编码解码系统"<cout<<"******************************"<cout<<"
(1)要初始化赫夫曼链表请输入'i'"<cout<<"
(2)输入要编码的字符'w'"<cout<<"(3)要编码请输入'e'"<cout<<"(4)要译码请输入'd'"<cout<<"(5)要打印编码请输入'p'"<cout<<"(6)要打印赫夫曼树请输入't'"<cout<<"(7)要离开请输入'q'"<if(flag==0)cout<<"\n请先初始化赫夫曼链表,输入'i'"<cin>>choice;
switch(choice)
{
case'i':
Initialization();
break;
case'w':
InputCode();
break;
case'e':
Encoding();
break;
case'd':
Decoding();
break;
case'p':
Code_printing();
break;
case't':
Tree_printing(HT,2*n-1);
break;
case'q':
break;
default:
cout<<"inputerror"<}
}
free(z);
free(w);
free(HT);
}
利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本,但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。
对于双工信道(