数据结构课程设计赫夫曼编码讲解文档格式.docx
- 文档编号:18021176
- 上传时间:2022-12-12
- 格式:DOCX
- 页数:23
- 大小:416.03KB
数据结构课程设计赫夫曼编码讲解文档格式.docx
《数据结构课程设计赫夫曼编码讲解文档格式.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计赫夫曼编码讲解文档格式.docx(23页珍藏版)》请在冰豆网上搜索。
(1)已知某系统在通信联络中只可能出现八种字符,其频率分别为0.05,0.29,0.07,0.08,0.14,0.23,0.03,0.11,试设计赫夫曼编码。
(2)用下表给出的字符集和频度的实际统计数据建立赫夫曼树,并实现以下报文的编码和译码:
“THISPROGRAMEISMYFAVORITE”。
字符
A
B
C
D
E
F
G
H
I
J
K
L
M
频度
186
64
13
22
32
103
21
15
47
57
1
5
20
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
63
48
51
80
23
8
18
16
4.实现提示
(1)编码结果以文本方式存储在文件Codefile中。
(2)用户界面可以设计为“菜单”方式:
显示上述功能符号,再加上“Q”,表示退出运行Quit。
请用户键入一个选择功能符。
此功能执行完毕后再显示此菜单,直至某次用户选择了“Q”为止。
(3)在程序的一次执行过程中,第一次执行I,D或C命令之后,赫夫曼树已经在内存了,不必再读入。
每次执行中不一定执行I命令,因为文件hfmTree可能早已建好。
二、需求分析
根据给出的信息,构造一颗哈夫曼树,并得到每个字符对应的哈夫曼码,同时存入文件hfmTree中。
打印代码文件(Print)。
打印赫夫曼树(Treeprinting)。
三、设计概要
1、总体流程图:
2、建立哈夫曼树
建立哈夫曼树
输入字符及权值
建立哈夫曼树并把哈夫曼码写入hfmTree
输出每个字符的哈夫曼码
结束
3、编码
因为可能事先已经运行过I:
建立哈夫曼树操作,所以hfmTree可能已经存在每个字符的哈夫曼码。
编码
Y:
通过hfmTree中的哈夫曼树进行编码
输入要编码的字符串
将码值写入CodeFile
判断hfmTree中是否有树
N:
通过内存中的哈夫曼树进行编码
4、译码
5、打印代码
从文件CodeFile读入代码
打印代码
按每行50将代码输出在界面
四、详细设计
1、建立哈夫曼树
//-------------------------------------初始化--------------------------------------
intmin(HfmTeee&
t,intx)//查找权值最小的树
{
intflag;
intk=999999999;
for(inti=1;
i<
=x;
i++)
{
if(t[i].weight<
k&
&
t[i].parent==0)
{
k=t[i].weight;
flag=i;
}
}
t[flag].parent=1;
returnflag;
}
voidFind(HfmTeee&
H,intx,int*p1,int*p2)//查找权值最小的两棵树
*p1=min(H,x);
*p2=min(H,x);
if(*p1>
*p2)
intt=*p1;
*p1=*p2;
*p2=t;
voidCreateHfmTree(HfmTeee&
H,HuffCode&
Code,intn)//构建哈夫曼树
inti,start,c,f,m,w;
intp1,p2;
char*cd,z;
if(n<
=1){//如果节点小于1,无法构造!
return;
}
m=2*n-1;
H=(HfmTeee)malloc((m+1)*sizeof(HtNode));
for(i=1;
=n;
++i)
{
printf("
请输入第%d字符信息和权值:
"
i);
scanf("
%c%d"
&
z,&
w);
while(getchar()!
='
\n'
)
continue;
H[i].ch=z;
H[i].weight=w;
H[i].parent=0;
H[i].lchild=0;
H[i].rchild=0;
for(;
=m;
H[i].ch='
0'
;
H[i].weight=0;
for(i=n+1;
Find(H,i-1,&
p1,&
p2);
H[p1].parent=i;
H[p2].parent=i;
H[i].lchild=p1;
H[i].rchild=p2;
H[i].weight=H[p1].weight+H[p2].weight;
Code=(HuffCode)malloc((n+1)*sizeof(char*));
cd=(char*)malloc(n*sizeof(char));
cd[n-1]='
\0'
++i)//进行哈夫曼编码
start=n-1;
for(c=i,f=H[i].parent;
f!
=0;
c=f,f=H[f].parent)
{
if(H[f].lchild==c)
cd[--start]='
else
1'
}
Code[i]=(char*)malloc((n-start)*sizeof(char));
strcpy(Code[i],&
cd[start]);
ofstreamoFile("
hfmTree.txt"
ios:
:
trunc|ios:
out);
//以清空方式打开文件,并写入
if(!
oFile)
cout<
<
Cannotopenthefile!
endl;
return;
oFile<
n<
oFile<
H[i].ch<
:
"
Code[i]<
oFile.close();
cout<
赫夫曼树已经创建完毕,并且已经放入hfmTree.txt文件中!
;
free(cd);
ok=1;
}
2、编码
//-------------------------------------编码--------------------------------------
voidEncoding(HfmTeeeH,HuffCodecode,intleaves)
charstr[100];
请输入字符:
getchar();
gets(str);
ToBeTran.txt"
out|ios:
app);
str<
ofstreamoFile1("
CodeFile.txt"
if(ok==0)
ifstreamiFile("
in);
if(!
iFile)
cout<
对不起您未建哈夫曼树同时文件中也不存在!
return;
charch,th,str1[20];
iFile>
>
leaves;
H=(HfmTeee)malloc((leaves+1)*sizeof(HtNode));
code=(HuffCode)malloc((leaves+1)*sizeof(char*));
intant=1;
while(iFile.peek()!
=EOF)
iFile.get(ch);
//接收上一行的换行符
iFile>
th>
str1;
intl=strlen(str1);
H[ant].ch=ch;
code[ant]=(char*)malloc((l+1)*sizeof(char));
strcpy(code[ant++],str1);
iFile.close();
for(inti=0;
strlen(str);
for(intj=1;
j<
=leaves;
j++)
if(str[i]==H[j].ch)
{
oFile1<
code[j];
break;
}
oFile1<
oFile1.close();
译码结束,字符已经存入CodeFile.txt文件中!
endl<
3、译码
//-------------------------------------译码--------------------------------------
voidDecoding(HfmTeeeh,HuffCodecode,intleaves)
charstr[100000];
chartemp[100];
对CodeFile.txt的数据进行编译……"
<
ifstreamiFile1("
iFile1)
iFile1>
h=(HfmTeee)malloc((leaves+1)*sizeof(HtNode));
while(iFile1.peek()!
iFile1.get(ch);
iFile1>
h[ant].ch=ch;
iFile1.close();
ifstreamiFile("
当前无可译的代码!
Textfile.txt"
您还未构建哈夫曼树,请先建树!
iFile>
str;
while(iFile.peek()!
=EOF)
intk=0;
intant=0;
while(str[k]!
)
for(inti=1;
intx=k;
intj;
for(j=0;
strlen(code[i]);
j++,x++)
temp[j]=str[x];
temp[j]='
if(strcmp(code[i],temp)==0)
{
oFile<
h[i].ch;
//res[ant++]=h[i].ch;
k=k+strlen(code[i]);
break;
}
iFile.close();
编译完成,编译后的结果已经存入Textfile.txt中"
}
4、打印代码文件
//-------------------------------------打印代码文件--------------------------------------
voidPrint()
{
CodeFile文件不存在或未找到药打印的代码!
\t输出CodeFile.txt中的代码,每行50个:
stringstr;
intant=1;
intl=str.length();
for(inti=0;
l;
i++)
str[i];
if(ant%50==0)
cout<
ant++;
5、主函数
//-------------------------------------主函数--------------------------------------
voidmain()
HfmTeeeh;
HuffCodecode;
intn=0;
charchoice='
a'
\n"
\t\t\t"
计科
(1)班"
2011329620107"
程方远\n"
while(choice!
Q'
choice!
q'
*************************赫夫曼编码/译码器*************************\n"
I.Init"
E.Encoding"
D.Decoding"
P.Print"
Q.Exit\n"
请输入您要操作的步骤:
cin>
choice;
switch(choice)
case'
I'
case'
i'
请输入字符个数:
cin>
n;
getchar();
CreateHfmTree(h,code,n);
break;
E'
e'
Encoding(h,code,n);
D'
d'
Decoding(h,code,n);
P'
p'
Print();
case'
五、调试分析
1、构建哈夫曼树
测试数据:
2、编译
编译字符:
THISPROGRAMEISMYFAVORITE
时间复杂度:
min(HfmTeee&
t,intx)O(n)
CreateHfmTree(HfmTeeeH,HuffCodecode,intleaves)O(n)
Decoding(HfmTeeeh,HuffCodecode,intleaves)O(n)
Encoding(HfmTeeeH,HuffCodecode,intleaves)O(n)
Print()O
(1)
调试分析:
1、写完运行,有很多细节错误。
解决方法:
根据错误提示依次修正。
2、第一次成功运行,因为有字符的输入,没有注意,导致在建树的时候,第一个字符变成了回车符。
在输入n之后补加了一句getchar();
语句以解决错误。
3、运行时,提示警告n,h,code未初始化。
对n初始化为0,h,code为NULL。
4、从文件中读入时出现错误,以及对code和h的申请动态有误。
问题解决:
因为通过”>
”文件读取时,以空格作为结束符,因此,通过get读取,iFile.get(ch)读取时可以读取所以字符,包括空格和换行符,因此,iFile.get(ch)要运行两次,第一次,目的是接受换行符,第二次,接收的才是相应的字符。
5、运行时提示错误:
无法写入!
设定断点后找到,在编码、译码函数中,在从文件中读取哈夫曼码时,二阶字符指针code只进行了依次申请二维数组空间,将代码复制给code[i]时,未对code[i]进行申请动态。
code[i]=(char*)malloc((l+1)*sizeof(char));
六、总结
首先要说的是,题意的不明确,或者说是不合理:
“在程序的一次执行过程中,第一次执行I,D或C命令之后,赫夫曼树已经在内存了,不必再读入。
”
此句话有歧义。
本次课程设计,主要是为了熟悉对哈夫曼树的建立以及哈夫曼码的使用,在建树的时候,可以通过构建一个节点:
typedefstruct
charch;
intparent;
intlchild;
intrchild;
intweight;
}HtNode,*HfmTeee;
以存储树节点的信息,在通过一个二阶字符指针:
typedefchar**HuffCode;
来存储经过编译后的代码。
我在写的时候,刚开始考虑到I:
初始化操作每次运行exe时,可能不一定运行,可以从hfmTree文件中读入个字符的哈夫曼码值,因此在定义结构体数组的时候
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 课程设计 赫夫曼 编码 讲解