课程设计报告Word文档下载推荐.docx
《课程设计报告Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《课程设计报告Word文档下载推荐.docx(21页珍藏版)》请在冰豆网上搜索。
![课程设计报告Word文档下载推荐.docx](https://file1.bdocx.com/fileroot1/2023-1/22/57afa13a-5ee3-4229-acea-02de09042fd2/57afa13a-5ee3-4229-acea-02de09042fd21.gif)
(4)显示指定的压缩文件和文本文件;
(5)界面友好,易与操作。采用菜单方式进行选择。
【选做内容】
(1)把哈夫曼编码用二进制位紧缩到一个变量中,利用位运算进行真正的数据压缩,并求压缩比。
(2)显示哈夫曼树;
(3)使用汉字显示。
我选做第二条显示哈夫曼树。
实习进度安排及主要内容:
第一周:
一、需求分析:
利用哈弗曼树编写一个简单的编码/译码系统;
用户可以自行创建一个文本文件,程序对该文本文件中的字符进行哈弗曼编码,生成后缀名为.cod的编码文件即压缩文件,反过来,程序也可以将一个压缩文件译码还原为一个文本文件(.txt)。
二、概要设计:
通过需求分析可将程序大致分为三个部分:
编码,译码,显示哈夫曼树。
首先根据题目确定该程序的存储结构为哈夫曼树,我们需要定义哈弗曼树节点的结构体以及哈夫曼编码的结构体。定义代码如下:
typedefstructnode//定义哈夫曼树节点结构体
{
intweight;
intparent,lchild,rchild;
structnode*LChild,*RChild,*Parent;
//分别指向该节点的左孩子,右孩子,和双亲节点
structnode*next;
//指向建立的哈夫曼树的下一个节点
}HFMNode,*HFMTree;
typedefstruct//定义哈夫曼编码的结构体
charch;
//存储对应的字符
charcode[N+1];
//存储对应字符的编码
intstart;
//存储编码的起始位置
}CodeNode;
1、编码:
(1)函数open(chars[])用来打开用户指定的文本文件,流程图如下:
(2)函数Save(chars[])保存字符或编码到文件中,流程图如下:
(3)函数SearchStr(chars[],charstr[],intcount[])查找字符串中字符的个数和每个字符出现的次数。流程图如下:
#defineN128
(4)函数SelectMin(HFMTreeHT,intk,HFMTree*HT1,HFMTree*HT2)查找哈夫曼链表中两个权值最小的节点。流程图如下:
(5)函数CreatHFMTree(HFMTree*HT,intcount[])创建哈夫曼树。流程图如下:
(6)函数HFMCode(HFMTreeHT,CodeNodeHC[],charstr[])从每个叶子节点开始,利用哈夫曼树对每个字符进行编码,最终建立一个哈夫曼表。intn存储真正叶子节点个数。流程图如下:
(7)函数TotalCoding(chars[],CodeNodeHC[],charcode[])利用哈夫曼编码表对整个字符串进行编码。流程图:
2.解码:
(1)函数DeCoding(charcode[],HFMTreeHT,charstr[],chars[])对哈夫曼编码进行解码,放入字符串s中。流程图如下:
(2)函数Coding(chars[],charstr[],charcode[],intcount[],HFMTree*HT,CodeNodeHC[])流程图如下:
(3)函数TransCode(charcode[],charstr[],charss[],HFMTree*HT,CodeNodeHC[])流程图如下:
3.显示哈夫曼树:
(1)函数print(HFMTreeHT,CodeNodeHC[],charstr[],intn)显示哈弗曼表。流程图如下:
4.主函数测试:
要求界面友好所以用switch语句构造菜单。
第二周:
三、详细设计:
程序源代码如下:
#include<
stdio.h>
stdlib.h>
string.h>
malloc.h>
#defineM10000//定义字符串最大长度
#defineN128//定义叶子节点个数
{intweight;
typedefstruct//定义哈夫曼编码的结构体
{charch;
intn;
//存储真正叶子节点个数
typedefint*&
WW;
voidOpen(chars[])//打开存放字符或编码的文件,将其存入字符串数组中
{charname[10];
FILE*fp;
inti=0;
printf("
请输入要打开的文件名:
"
);
gets(name);
//要打开的文件名
if((fp=fopen(name,"
rt"
))==NULL)
{printf("
打开失败!
\n"
exit
(1);
}
s[i++]=fgetc(fp);
while(s[i-1]!
=EOF)
s[i]='
\0'
;
//存取字符串结束
fclose(fp);
voidSave(chars[])//保存字符或编码到文件中
请输入要保存的文件名:
wt"
存储失败!
fputs(s,fp);
\n保存成功,文件名为:
%s。\n"
name);
\n按回车键继续..."
getchar();
voidSearchStr(chars[],charstr[],intcount[])//查找字符串中字符的个数和每个字符出现的次数
{
inti,j,k=0;
for(i=0;
i<
N;
i++)//初始化每个字符出现的次数
count[i]=0;
s[i];
i++)
{for(j=0;
j<
k;
j++)//在str[]中查找是否有该字符
if(str[j]==s[i])
{count[j]++;
break;
if(j==k)//在str[]中无该字符,将其存入最后一个单元
{str[k]=s[i];
count[k++]++;
}}
str[k]='
//将字符串结尾置\0
n=k;
//将实际的字符个数作为叶子节点个数存入n
voidSelectMin(HFMTreeHT,intk,HFMTree*HT1,HFMTree*HT2)//查找哈夫曼链表中两个权值最小的节点
{inti,min;
HFMTreep;
min=32767;
for(i=0,p=HT;
i++,p=p->
next)
if(p->
weight<
min&
&
p->
Parent==0)
{min=p->
weight;
*
HT1=p;
Parent==0&
p!
=*HT1)//令第二个最小的节点不等于第一个节点
*HT2=p;
voidCreatHFMTree(HFMTree*HT,intcount[])//创建哈夫曼树
{inti;
HFMTreep,HT1,HT2;
//HT1,HT2分别存放权值最小和次小的节点的位置
p=*HT=(HFMTree)malloc(sizeof(HFMNode));
next=p->
LChild=p->
RChild=p->
Parent=NULL;
//初始化哈夫曼链表且有2n-1个节点
for(i=1;
2*n-1;
{p->
next=(HFMTree)malloc(sizeof(HFMNode));
p=p->
next;
}for(i=0,p=*HT;
n;
i++)//将各个字符出现的次数作为权值
{//存入哈夫曼链表的前n个单元中
weight=count[i];
for(i=n;
i++)//将后n-1个节点赋权值,建树
{SelectMin(*HT,i,&
HT1,&
HT2);
//每次从前i个节点中选取权值最小的两个节点
HT1->
Parent=HT2->
Parent=p;
LChild=HT1;
RChild=HT2;
weight=HT1->
weight+HT2->
//将两个节点的权值相加存入最后一个节点中
//p指向下一个没有存储权值的节点
voidHFMCode(HFMTreeHT,CodeNodeHC[],charstr[])
{//从每个叶子节点开始,利用哈夫曼树对每个字符进行编码,最终建立一个哈夫曼表
inti;
HFMTreeq,p=HT;
i++)//将字符存入哈夫曼编码结构体数组的字符单元中
{HC[i].ch=str[i];
HC[i].code[n-1]='
//初始化编码的最后一位
{HC[i].start=n-1;
for(q=p;
q->
Parent;
q=q->
Parent)//判断q所指向的节点,左孩子置0,右孩子置
if(q==q->
Parent->
LChild)
HC[i].code[--HC[i].start]='
0'
elseHC[i].code[--HC[i].start]='
1'
//判断下一个叶子节点
voidTotalCoding(chars[],CodeNodeHC[],charcode[])
{//利用哈夫曼编码表对整个字符串进行编码
inti,j;
code[0]='
//编码数组初始化
i++)//将每个字符在哈夫曼编码表中对应的编码存入存放总编码的数组中
for(j=0;
j++)
if(s[i]==HC[j].ch)
strcpy(code+strlen(code),HC[j].code+HC[j].start);
voidDeCoding(charcode[],HFMTreeHT,charstr[],chars[])
{//对哈夫曼编码进行解码,放入字符串s中
inti,j,k=0;
HFMTreeroot,p,q;
for(root=HT;
root->
root=root->
Parent);
//用root指向哈夫曼树的根结点
for(i=0,p=root;
code[i];
i++)//从根结点开始按编码顺序访问树
{if(code[i]=='
)
LChild;
elsep=p->
RChild;
LChild==NULL&
RChild==NULL)//到根节点时将该节点对应的字符输出
{for(j=0,q=HT;
q!
=p;
next,j++);
s[k++]=str[j];
p=root;
//回溯到根结点
}}
s[k]='
//解码完毕,在字符串最后一个单元存入'
voidCoding(chars[],charstr[],charcode[],intcount[],HFMTree*HT,CodeNodeHC[])
\n打开存放字符串的文件...\n\n"
Open(s);
//打开源码文件
SearchStr(s,str,count);
//查找字符串中不同的字符及其出现的次数
CreatHFMTree(HT,count);
//用每个字符出现的次数作为叶子节点的权值建立哈夫曼树
HFMCode(*HT,HC,str);
//利用哈夫曼树对每个叶子节点进行编码,存入编码表中
TotalCoding(s,HC,code);
//利用编码表对字符串进行最终编码
\n读入的字符串为:
puts(s);
\n最终的哈夫曼编码是:
puts(code);
\n保存编码,"
Save(code);
//保存最终的哈夫曼编码
voidTransCode(charcode[],charstr[],charss[],HFMTree*HT,CodeNodeHC[])
\n打开编码的文件...\n\n"
Open(code);
//打开编码文件
DeCoding(code,*HT,str,ss);
//将编码进行解码存入字符串数组ss[]中
\n得到的最终字符串为:
puts(ss);
\n保存译码,"
Save(ss);
//保存译码后的字符串
voidprint(HFMTreeHT,CodeNodeHC[],charstr[],intn)//打印哈弗曼表
{inti=0;
intm=2*n-1;
HFMCode(HT,HC,str);
HFMTreep=HT;
\n哈弗曼树\n"
printf("
iwplr\n"
for(p=HT+1,i=1;
=m;
i++,p++)
printf("
%d%d%d%d%d\n"
i,p->
weight,p->
parent,p->
lchild,p->
rchild);
voidmain()//主函数
{chars[M],ss[M];
//定义字符串数组,s[]存放将要编码的字符串,ss[]存解码后的字符串
charstr[N];
//存放输入的字符串中n个不同的字符
intcount[N];
//存放n个不同字符对应的在原字符串中出现的次数
charcode[M];
//存放最终编码完成后的编码
charchoice;
HFMTreeHT;
//定义一个哈夫曼树的链表
CodeNodeHC[N];
//定义一个哈夫曼编码表的数组,存放每个字符对应的哈夫曼编码
do
\n\n"
********哈夫曼编码/译码器*******\n"
****\n"
**1.对文件进行哈弗曼编码。**\n"
**2.对编码后的文件进行译码。**\n"
**3.显示哈夫曼树**\n"
Printf("
**0.退出系统。**\n"
**请输入相应操作的序号(0-3)**\n"
********************************\n"
scanf("
%c"
&
choice);
switch(choice)
{case'
:
Coding(s,str,code,count,&
HT,HC);
//对字符串进行编码
case'
2'
TransCode(code,str,ss,&
//对编码进行解码
3'
print(HT,HC,str,n);
break;
default:
输入错误!
请重新输入!
}while(choice!
='
四、调试分析
1.errorC2059:
syntaxerror:
'
]'
HFMCode(HT,HC,str[]);
//错误指向这一行通过分析应该把str[]改为str,因为函数HFMCode的最后一个参数是
一个char类型的变量而不是一个数组,所以应该把"
[]"
去掉。
.........}
2.errorC2065:
choice'
:
undeclaredidentifier
//错误指向这一行,通过提示知道,此行的变量choice在之前没有定义,需要在此行之前添加语句"
charchoice"
3.errorC2039:
parent'
isnotamemberof'
node'
rchild,p->
lchild);
//错误指向这一行,通过查找语句,可知道node结构体内没有定义parent,而是Parent,所以应该把头字母改成小写。
五、测试数据
6、心得体会:
通过这次学习我深刻的感觉到自己的基本功不足,一些小的程序都需要一些时间去考虑,没有完全的做到一看要求就把程序写出来的程度,我还需要提高自己对基本功的巩固,还有就是遇到了很多难题,自己怎么也解决不了,上网找了很多资料,给了很多借鉴。同时,也了解了要真正做出一个程序很不容易,但只要用心去做,总会有收获。特别是遇到一个问题,想办法去解决,最终找到方法是,心里的喜悦是难以形容的。所以要有耐心,有恒心,有决心,只要认真排查,问题都会得到解决的。
7、参考文献
1.《C程序设计(第三版)》谭浩强
2.《数据结构(C语言版)》严蔚敏吴伟民清华大学出版社
成绩:
指导教师/带队教师(签字)
年月日