Huffman编码译码器.docx
- 文档编号:8670786
- 上传时间:2023-02-01
- 格式:DOCX
- 页数:16
- 大小:297.70KB
Huffman编码译码器.docx
《Huffman编码译码器.docx》由会员分享,可在线阅读,更多相关《Huffman编码译码器.docx(16页珍藏版)》请在冰豆网上搜索。
Huffman编码译码器
课程设计:
Huffman编码/译码器
一、任务描述
任务:
设计一个利用哈夫曼算法的编码和译码系统。
要求:
建立一个文本文件,统计该文件中各字符频率,对各字符进行Huffman编码,将该文件翻译成Huffman编码文件,再将Huffman编码文件翻译成原文件。
“压缩文件”即:
读文件、统计文件中的字符个数、对文件进行哈夫曼编码和译码、并将编码译码后的字符存储在文件中。
根据以上任务说明,设计数据结构,并设计程序完成功能。
二、问题分析
分析设计课题的要求,要求编程实现以下功能:
(1)创建最小Huffman树;
(2)统计文件中个字符的个数(频率);
(3)对个字符进行编码;
(4)将原文件翻译成编码文件;
(5)将编码文件翻译成原文件;
(6)创建yuanwj.txt、yima.txt、out.txt
三、数据结构设计
选用二叉树链表实现。
有关的定义如下:
typedefstructnode//哈夫曼树节点的结构体定义
{
chardata;
intweight;
intparent,lc,rc;
}NODE;
typedefstructabc
{
charch;
charstr[20];
ints;
}ABC;
四、功能设计
(一)、主控菜单设计
为实现编码译码的操作功能,首先设计一个含有多个菜单项的主控菜单程序,然后再为这些菜单项配上相应的功能。
程序运行后,给出4个菜单项的内容和输入提示,如下:
1、键盘输入进行编码;
2、读文件进行编码;
3、译码;
4、退出系统;
(二)程序模块结构
由课题要求可将程序划分为以下几个模块:
(1)统计字符的频度tongji();
(2)建立哈弗曼树haffman();
(3)编码huffmancode();
(4)输入input();
(5)输出output();
(6)译码yima();
(三)、函数调用关系
其中main()是主函数,它进行菜单驱动,根据选择项0~3调用相应的函数。
main()函数使用switch循环实现重复选择。
其循环结构如下:
switch(choice)
{
case1:
printf("\t请输入字符串:
\n\t");fflush(stdin);
gets(s);
fp=fopen("D:
\\yuanwj.txt","w");
fputs(s,fp);
fclose(fp);
case2:
tongji();
haffman();
huffmancode();
printf("您所输入的字母为:
");
input();
printf("您所输入的字母对应的编码为:
");
output();
getch();
break;
case3:
printf("译码为:
");
yima();getch();
break;
case0:
return;
}
(四)文件结构
1、mn.h:
主菜单函数的声明
2、mn.cpp:
主菜单函数的实现
3、main.cpp:
主函数
(五)各函数算法设计
1、voidtongji()
{
charstr1[100];
charch,s;
inti,j,count1=0,count2,k;//count1为存入字符的个数
FILE*fp;
if((fp=fopen("D:
\\yuanwj.txt","rt"))==NULL)
{
printf("\n无法打开!
\n");
getchar();
exit
(1);
}
ch=fgetc(fp);
i=1;
while(ch!
='#')
{
str1[i]=ch;//将输入的字符存入str[i]
count1=i;
i++;
ch=fgetc(fp);
}
fclose(fp);//关闭文件
k=0;
for(i=1;i<=count1;i++)
{
if(str1[i]!
='0')//字符串以'\0'结束
{
s=str1[i];
count2=0;
for(j=1;j<=count1;j++)//遍访字符串统计频率count2
if(str1[j]==s)
{
count2++;
str1[j]='0';
}
r[k].data=s;//将每个字符分别赋给r[k].data,这里已经没有重复字符
r[k].weight=count2;//频率即为权值
r[k].lc=r[k].rc=r[k].parent=0;//初始化
k++;
}
}
n=k;
}
//哈夫曼树的建立
2、voidhaffman()
{
inti,j,m1,m2,x1,x2;//m1,m2分别存放最小和次小权值,
//x1,x2分别存放m1和m2的结点地址即该结点在数组r中的下标
i=0;
while(i { m1=m2=32767;//初始化 x1=x2=0; for(j=0;j if((r[j].weight { m2=m1; x2=x1; m1=r[j].weight; x1=j; } elseif((r[j].weight { m2=r[j].weight; x2=j; } r[x1].parent=n+i; r[x2].parent=n+i; r[n+i].weight=r[x1].weight+r[x2].weight; r[n+i].lc=x1; r[n+i].rc=x2; r[n+i].parent=0; i++; } for(i=0;i { printf("字母%c的权值为: %d\n",r[i].data,r[i].weight); } } //编码 3、voidhuffmancode() { inti,j,k; for(i=0;i { H[i].ch=r[i].data;//将字符逐个存入H[i].ch H[i].str[19]='\0';//赋结束符 H[i].s=18;//字符串最大长度 } for(i=0;i { k=18;j=i;//从最后一位开始存储 while(r[j].parent! =0)//r[i]不是根结点 { if(r[r[j].parent].lc==j) { H[i].str[k]='0';//左孩子赋'0' H[i].s=k; k--; j=r[j].parent; } elseif(r[r[j].parent].rc==j) { H[i].str[k]='1';//右孩子赋'1' H[i].s=k; k--; j=r[j].parent; } } } for(i=0;i { printf("字母%c的编码为: ",H[i].ch); for(j=H[i].s;j<20;j++) printf("%c",H[i].str[j]); printf("\n"); } } //输入 4、voidinput() { FILE*fp; charch; if((fp=fopen("D: \\yuanwj.txt","rt"))==NULL) { printf("无法打开\n"); } ch=fgetc(fp);//从打开的fp所指向的文件中读取一个字符并送入ch中 while(ch! =EOF)//遇文件尾时返回EOF { putchar(ch);//每调用一次向显示器输出一个字符 ch=fgetc(fp); } printf("\n"); fclose(fp);//关闭文件 } //输出 5、voidoutput() { FILE*fp,*fq; inti; charch; if((fp=fopen("D: \\yuanwj.txt","rt"))==NULL) { printf("无法打开\n"); exit(0); } fq=fopen("D: \\out.txt","wt"); ch=fgetc(fp); while(ch! =EOF) { for(i=0;i if(H[i].ch==ch) { fputs(&H[i].str[H[i].s],fq); break; } ch=fgetc(fp); } fclose(fp); fclose(fq); if((fq=fopen("D: \\out.txt","rt"))==NULL) { printf("无法打开\n"); exit(0); } ch=fgetc(fq);//从打开的fq所指向的文件中读取一个字符并送入ch中 while(ch! =EOF) { putchar(ch);//每调用一次向显示器输出一个字符 ch=fgetc(fq);//从打开的fp所指向的文件中读取一个字符并送入ch中 } printf("\n"); fclose(fq); } 6、voidyima() { FILE*fp,*fq; intk; charch; if((fp=fopen("D: \\out.txt","rt"))==NULL) { printf("无法打开\n"); exit(0); } fq=fopen("D: \\yima.txt","wt"); k=2*n-2;//2n-2为根结点在数组r中的下标 ch=fgetc(fp);//从打开的fp所指向的文件中读取一个字符并送入ch中 while(ch! =EOF) { if(ch=='0') k=r[k].lc; else k=r[k].rc; if(r[k].lc==NULL&&r[k].rc==NULL)//r[k]为叶子结点 { fputc(r[k].data,fq);//输出字符 k=2*n-2; } ch=fgetc(fp); } fclose(fp); fclose(fq); if((fq=fopen("D: \\yima.txt","rt"))==NULL) { printf("无法打开\n"); exit(0); } ch=fgetc(fq); while(ch! =EOF) { putchar(ch); ch=fgetc(fq); } printf("\n"); fclose(fq); } 五、测试数据与结果 1、测试数据 输入字符串为: Iwillmeetyouat6.amtomorrowmornimng. 文件保存路径: D: \\yuanwj.txt;D: \\out.txt;D: \\yima.txt. 2、测试结果 (1)、主菜单显示如下: (2)输入字符串,并进行编码 (3)译码 (4)原文件 Yuanwj.txt 编码文件: out.txt 译码文件: yima.txt 六、结束语 哈夫曼编译码器设计,课程设计中,通过该题目的设计过程,我加深了对树的数据结构以及二叉树的逻辑结构,存储结构的理解,对树的数据结构上基本运算的实现有所掌握,对课本中所学的各种数据结构进一步理解和掌握,学会了如何把学到的知识用于解决实际问题,锻炼了自己动手的能力。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Huffman 编码 译码器