数据结构课程设计哈夫曼编译码文档格式.docx
- 文档编号:19867360
- 上传时间:2023-01-11
- 格式:DOCX
- 页数:21
- 大小:135.75KB
数据结构课程设计哈夫曼编译码文档格式.docx
《数据结构课程设计哈夫曼编译码文档格式.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计哈夫曼编译码文档格式.docx(21页珍藏版)》请在冰豆网上搜索。
2.2设计思想
哈夫曼编码(HuffmanCoding)是一种编码方式,以哈夫曼树─即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩。
是指使用一张特殊的编码表将源字符(例如某文件中的一个符号)进行编码。
这种方法是由David.A.Huffman发展起来的。
例如,在英文中,e的出现概率很高,而z的出现概率则最低。
当利用哈夫曼编码对一篇英文进行压缩时,e极有可能用一个位(bit)来表示,而z则可能花去25个位(不是26)。
用普通的表示方法时,每个英文字母均占用一个字节(byte),即8个位。
二者相比,e使用了一般编码的1/8的长度,z则使用了3倍多。
倘若我们能实现对于英文中各个字母出现概率的较准确的估算,就可以大幅度提高无损压缩的比例。
2.3系统模块划分
图2-3哈夫曼编/解码器的程序结构图
2.3.1初始化算法:
程序从文件abc.txt中获取26个英文字母的权值。
2.3.2编码算法:
(1)对输入的一段欲编码的字符串进行统计各个字符出现的次数,并它们转化为权值{w1,w2,……,wN}构成n棵二叉树的集合F={T1,T2,……,Tn}把它们保存到结构体数组HT[n]中,其中{Ti是按它们的ASCⅡ码值先后排序。
其中每棵二叉树Ti中只有一个带权为Wi的根结点的权值为其左、右子树上根结点的权值之和。
(2)在HT[1..i]中选取两棵根结点的权值最小且没有被选过的树作为左右子树构造一棵新的二叉树,且置新的二叉树的根结点的权值为左、右子树上根结点的权值之和。
(3)哈夫曼树已经建立后,从叶子到根逆向求每一个字符的哈夫曼编码。
2.3.3译码算法:
译码的过程是分解电文中字符串,从根出发,按字符'
0'
或'
1'
确定找左孩子或右孩子,直至叶子结点,便求的该子串相应字符并输出接着下一个字符。
3.数据结构与算法描述
3-1
typedefstruct
{intweight;
intparent,lchild,rchild;
}HTNode,*HuffmanTree;
//动态分配数组存储赫夫曼树
typedefchar**HuffmanCode;
//动态分配数组存储赫夫曼编码表
3-2intmin(HuffmanTreet,inti)//---------求赫夫曼编码-------------
3-3voidselect(HuffmanTreet,inti,int&
s1,int&
s2)//----slect函数----
3-4
voidHuffmanCoding(HuffmanTree&
HT,HuffmanCode&
HC,int*w,intn)
//w存放n个字符的权值(均>
0),构造赫夫曼树HT,并求出n个字符的赫夫曼编码HC
3-5voidInitialization()//----------初始化赫夫曼链表--------------
3-6voidInputCode()//---------获取报文并写入文件-------------
3-7voidEncoding()//----------------编码函数------------------
3-8voidDecoding()//-----------------译码函数-----------------
3-9voidCode_printing()//-------------打印编码的函数--------------
3-19voidcoprint(HuffmanTreestart,HuffmanTreeHT)
//------------------------打印赫夫曼树的函数-----------------------
3-20voidmain()//--------------------主函数-------------------
4.测试结果与分析
A
186
B
64
C
13
D
22
E
32
F
103
G
21
H
15
I
47
J
57
K
L
M
20
N
O
63
P
Q
1
R
48
S
51
T
80
U
23
V
8
W
18
X
Y
16
Z
表4-1abc.txt文件中的字母和权值
声明:
程序预先将Huffman编码解码所需的26个字母和权值保存在根目录下的abc.txt文件下。
4-1.按照程序提示输入i对Huffman进行初始化。
4-2.初始化后程序对abc.txt文件中的数据进行读取并运行编码函数进行哈夫曼编码。
然后将字母、权值和哈夫曼编码存在根目录下的htmTree.txt文件中。
在屏幕显示出字符、权值、编码。
4-3.输入w进入待编码字符输入窗口,并键入字符串(注意单词间无空格)“happynewyear”。
4-4.可以看出所获得的字符串已经存入根目录下的tobetran.txt文件中。
4-5.输入e进行编码、译码和打印编码功能。
4-6.输入t打印哈夫曼树。
由于哈夫曼树过于巨大,一次截屏无法完全显示,使用两次截屏。
以上两幅图显示出来程序编出的哈夫曼树的形状。
打印出来的图形与教科书上的常见哈夫曼树略有不同,左边的数是右边数的父节点。
4-7.输入q退出程序。
5.总结
5-1、用户界面设计为“菜单”模式,使人们更加容易使用。
5-2、在程序的一次执行过程中,第一次执行e命令之后,哈夫曼树已经在内存了,不必再读入。
5-3.在编程中使用了很不规范的编程方法,应用了一些临时变量来实现功能,,而大量临时变量在代码中没有很好地进行命名。
这给程序的阅读和维护带来了极大的困难。
5-4.本程序仅能对26个小写字母构成的字符串进行处理,并不具有对汉字等的编码处理能力。
5-5.设计中得到了老师和广大同学的帮助,并参考了网络上的优秀论文和纸质文件,使我的程序设计能够较为顺利的进行下去。
在此我衷心感谢我的老师同学和对以上资源的作者。
6.参考文献
A:
书籍资料
[1]李春葆《数据结构教程上机实验指导》北京:
清华大学出版社
[2]严蔚敏吴伟民《数据结构(C语言版)》北京:
[3]苏仕华《数据结构课程设计》北京:
机械工业出版社
B:
网络资料
[1]哈夫曼编/译码器(课程设计)
[2]哈夫曼编码
附录程序源代码
//哈夫曼编/译码器(课程设计)2008/5/21
#include<
iostream.h>
fstream.h>
iomanip.h>
string.h>
malloc.h>
stdio.h>
constintUINT_MAX=10000;
{
intweight;
//--------------------全局变量-----------------------
HuffmanTreeHT;
HuffmanCodeHC;
int*w,i,j;
constintn=26;
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].weight<
k&
&
t[j].parent==0)
k=t[j].weight,flag=j;
t[flag].parent=1;
returnflag;
}
//--------------------slect函数----------------------
voidselect(HuffmanTreet,inti,int&
s2)
{//s1为最小的两个值中序号小的那个
intj;
s1=min(t,i);
s2=min(t,i);
if(s1>
{
j=s1;
s1=s2;
s2=j;
}
//-------------------参考课本算法6.12-------------------
voidHuffmanCoding(HuffmanTree&
{//w存放n个字符的权值(均>
intm,i,s1,s2,start;
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;
parent=0;
lchild=0;
rchild=0;
for(;
=m;
++i,++p)
for(i=n+1;
++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++)
{//逐个字符求赫夫曼编码
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]='
else
HC[i]=(char*)malloc((n-start)*sizeof(char));
//为第i个字符编码分配空间
strcpy(HC[i],&
cd[start]);
//从cd复制编码(串)到HC
free(cd);
//释放工作空间
//----------------------初始化赫夫曼链表-------------------------
voidInitialization()
flag=1;
intnum2;
cout<
<
"
下面初始化赫夫曼链表"
endl;
w=(int*)malloc(n*sizeof(int));
//为第26个字符权值分配空间
z=(char*)malloc(n*sizeof(char));
//为第26个字符分配空间
\n依次显示"
n<
个字符与其权值和编码\n"
charbase[2];
//?
ifstreamfin("
abc.txt"
);
for(i=0;
n;
{
fin>
>
base;
*(z+i)=*base;
num2;
//上面123行
*(w+i)=num2;
}
HuffmanCoding(HT,HC,w,n);
//----------------------------------打印编码---------------------------------------
cout<
字符"
setw(6)<
权值"
setw(11)<
编码"
cout<
setw(3)<
*(z+i-1);
*(w+i-1)<
setw(12)<
HC[i]<
//--------------------------将赫夫曼编码写入文件----------------------------
下面将赫夫曼编码写入文件"
endl<
...................."
FILE*htmTree;
charr[]={'
'
'
};
if((htmTree=fopen("
htmTree.txt"
"
w"
))==NULL)
不能打开文件"
fputc(*(z+i),htmTree);
fputs(r,htmTree);
}
fprintf(htmTree,"
%6d"
*(w+i));
fputs(r,htmTree);
fputs(HC[i],htmTree);
fclose(htmTree);
已将字符与对应编码写入根目录下文件htmTree.txt中"
//--------------------------获取报文并写入文件---------------------------
voidInputCode()
FILE*tobetran;
charstr[100];
if((tobetran=fopen("
tobetran.txt"
不能打开文件"
请输入你想要编码的字符"
//字符个数应当小于100
gets(str);
fputs(str,tobetran);
获取报文成功"
fclose(tobetran);
cout<
报文存入根目录下的tobetran.txt文件中"
//---------------------------------编码函数---------------------------------
voidEncoding()
下面对目录下文件tobetran.txt中的字符进行编码"
FILE*tobetran,*codefile;
rb"
if((codefile=fopen("
codefile.txt"
wb"
char*tran;
i=99;
tran=(char*)malloc(100*sizeof(char));
while(i==99)
if(fgets(tran,100,tobetran)==NULL)
break;
*(tran+i)!
='
for(j=0;
if(*(z+j-1)==*(tran+i))
fputs(HC[j],codefile);
if(j>
n)
字符错误,无法编码!
…………编码完成…………"
endl;
编码写入目录下的codefile.txt中"
fclose(codefile);
free(tran);
//-------------------------译码函数---------------------------
voidDecoding()
{
下面对根目录下文件codefile.txt中的字符进行译码"
FILE*codef,*txtfile;
if((txtfile=fopen("
\\Textfile.txt"
txtfile=fopen("
Textfile.txt"
if((codef=fopen("
r"
codef=fopen("
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;
*(work+i-1)!
i2=*(work+i);
if(HT[i3].lchild==0)
*(work2+i4)=*(z+i3-1);
i4++;
i--;
elseif(i2=='
)i3=HT[i3].lchild;
)i3=HT[i3].rchild;
*(work2+i4)='
fputs(work2,txtfile);
…………译码完成…………"
内容写入根目录下的文件textfile.txt中"
free(work);
//释放工作区
free(work2);
//释放工作区
fclose(txtfile);
//关闭文件txtfile.txt
fclose(codef);
//关闭文件codef.txt
//-----------------------打印编码的函数----------------------
voidCode_printing()
下面打印根目录下文件CodePrin.txt中编码字符"
FILE*CodePrin,*codefile;
if((CodePrin=fopen("
CodePrin.txt"
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 课程设计 哈夫曼编 译码