哈夫曼树编码译码课程设计报告.docx
《哈夫曼树编码译码课程设计报告.docx》由会员分享,可在线阅读,更多相关《哈夫曼树编码译码课程设计报告.docx(9页珍藏版)》请在冰豆网上搜索。
![哈夫曼树编码译码课程设计报告.docx](https://file1.bdocx.com/fileroot1/2023-3/18/8f66e857-ce8f-4221-a712-7fa8710ec7c5/8f66e857-ce8f-4221-a712-7fa8710ec7c51.gif)
哈夫曼树编码译码课程设计报告
《数据结构》课程设计报告
设计题目:
__哈夫曼树编码译码
姓名:
______胡明号___________
学号:
______211011008________
专业:
_______嵌入式软件______
院系:
_计算机科学与技术学院___
班级:
________1003____________
指导教师:
_____高秀梅_________
2012年3月20日
摘要
哈夫曼编/译器设计:
利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
但是,这要求这发送端通过一个编码系统对待传数据预先编码,在发送端将传来的数据进行译码(复原)。
对于双工信道。
每端都需要一个完整的编译码系统。
本程序将为这样的信息收发站写一个哈夫曼的编译码系统。
哈夫曼编码/译码程序运行步骤:
字查找,从英文文章中识别出字符,并把字符插入到一棵二叉排序树中。
哈夫曼树中序遍历,是为了把英文文章中的不重复的字符保存起来。
哈夫曼编码,在已经构造好的霍夫曼树中从每个叶子结点出发追溯到树根,逆向找出霍夫曼树中叶子结点的编码,规定:
树中每个结点的左分支标上0,右分支标上1。
哈夫曼译码利用霍夫曼树实现对产生的编码文件的译码,译码过程为:
从根结点出发,按二进制位串的0或1进入左分支或右分支,当到达叶子结点时译出该叶子对应的单词或标点符号,若该编码文件尚未结束,则回到根结点继续进行上述过程。
运行环境:
windowsXP语言环境:
简体中文软件大小:
51KB编写工具:
MicrosoftVisualstudio2008
Abstract
Information:
Huffmancodingusedincommunicationcangreatlyimprovethechannelutilization,reducedtransmissiontime,andlowertransmissioncosts.However,thisrequiresthatthesenderthroughacodingsystemforpre-treatmentdata-coding,thetransmitterwillbesentfordecodingdata(recovery).Fordual-channel.Eachsideneedsacompleteencryptionsystem.ThisprocedurewillthisinformationhubsHuffmanwasoneoftheencryptionsystem.
Hoffmanncodeforcodingprocedurestorunthestepsand:
wordfromenglishinthewordsandpunctuationmarks;andinsertthewords,andpunctuationmarksasecondsortofatree.thetraversalorderhoffmann,toenglisharticlesdonotrepeatthewordsandpunctuationmarks.
Hoffmanntreeinordertotraverse;keepthecodehasbeenconstructedinhoffmanngoodhafmantreeleavesfromthestartdatesbacktotabulatetheroots;
Hoffmanndecoding;hafmantheimplementationofthecodetothecoding,codingproceduresfor:
fromstarttotabulatetherootsofbinaryof0or1totheleftorright,asubdivisionofabranchistotabulatetheleavesoftheleavestranslatethewordsorpunctuationmarks,ifthecodefileisnotfinishedbutistotabulatetheprocessofcontinuing.allthecode,codingproceduresareinthefile.
一、问题描述……………………………………………4
二、需求分析……………………………………………4
三、概要设计……………………………………………5
四、数据结构设计………………………………………7
五、算法设计……………………………………………7
六、程序测试与实现……………………………………9
七、调试分析…………………………………………12
八、心得体会…………………………………………12
一、问题描述
1、题目内容:
利用哈夫曼编码进行信息通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。
试写一个哈夫曼编/译码系统。
2、基本要求:
一个完整的系统应具有以下功能:
(1)初始化。
从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件中。
(2)编码。
利用已建好的哈夫曼树对文件中的正文进行编码,然后将结果存入文件中。
(3)译码。
利用已建好的哈夫曼树将文件中的代码进行译码,结果存入文件中。
(4)完成数据测试,要求编码字符不低于15个,编码文件的长度不低于50个字符。
(5)计算平均编码长度。
二、需求分析
一个完整的系统应具有以下功能:
1、初始化(Initialization)。
从终端读入字符集大小n,以及n个字符和n个权值,建立赫夫曼树。
1对赫夫曼树初始化。
2根据书本算法,对树进行从叶子到根的逆向求每个字符的赫夫曼编码。
3更新赫夫曼树。
2、编码(Encoding)。
利用已建好的哈夫曼树正文进行编码。
1将终端输入须要编码的语句逐字在已建好的赫夫曼树中查找。
2当在树中找到相匹配字符时,将该字符对应的赫夫曼编码同意保存。
③最后将数组中的编码在终端输出。
3、译码(Decoding)。
利用已建好的哈夫曼树将文件中的代码进行译码。
1获取须要译码的编码组。
2将编码逐一读入,并在赫夫曼中根据左‘0’右‘1’去查找字符。
3将译好的语句在终端输出。
三、概要设计
操作集合:
voidSelect(intcur,int&r1,int&r2);nodes[1~cur]中选择双亲为,权值最小的两个结点r1,r2
voidCreatHuffmanTree(charch[],intw[],intn);
public:
HuffmanTree(charch[],intw[],intn);由字符,权值和字符个数构造哈夫曼树
virtual~HuffmanTree();析构函数
stringEncode(charch);编码
LinkListDecode(stringstrCode);译码
本程序主要用到了三个算法。
(1)哈夫曼编码;
在初始化过程中间,要用输入的字符和权值建立哈夫曼树并求得
哈夫曼编码。
先将输入的字符和权值存放到一个结构体数组中,建立哈夫
曼树,将计算所得的哈夫曼编码存储到另一个结构体数组中。
(2)串的匹配;
在编码过程中间,要对已经编码过的代码译码,可利用循环,将
代码中的与哈夫曼编码的长度相同的串与这个哈夫曼编码比较,如果相等
就回显。
(3)二叉树的遍历
在印哈夫曼树(T)的中,因为哈夫曼树也是二叉树,所以就要利用二叉树的
先序遍历将哈夫曼树输出。
四、数据结构设计
structNode
{chardata;//节点数据域为字符型
Node*next;
Node(){next=NULL;};
Node(charitem,Node*link=NULL){data=item;next=link;};
}
structHuffmanTreeNode
{
intweight;
unsignedintparent,leftChild,rightChild;//双亲,左右孩子域
HuffmanTreeNode();
HuffmanTreeNode(intw,intp=0,intlChild=0,intrChild=0);
}
五、算法设计
1、算法分析(必须要用语言进行描述)
构造树:
初始化:
每个字符就是一个结点,字符的频度就是结点的权:
1、将结点按频度从小到大排序;
2、选取频度最小的两个结点,以它们为儿子,构造出一个新的结点;
新结点的权值就是它两个儿子的权值之和;
构造之后,从原来的结点序列里删除刚才选出的那两个结点,但同时将
新生成的结点加进去;
3、如果结点序列里只剩下一个结点,表示构造完毕,退出。
否则回到第一步。
编码:
编码:
可以假定,对某个结点而言,其左孩子在当前阶段的编码为0,右孩子的编
码为1。
这样就可以通过”树的遍历“的方式来生成字长—编码对照表
来到这里,基本上艰苦的已经完成了,对某个具体的字符串编码和解码就只
是简单的“查表—替换”的工作了。
解码:
解码也是个简单的查表、替换过程。
如果利用该种编码发送字符串,则它
的”字宁含—编码侧应表也必须发送过去,不然对方是不知道怎么解码的。
对给出的一串编码,从左向右,将编码组合起来并查表.
2、算法流程图
六、程序测试与实现
1、函数之间的调用关系
2、主程序
intmain(void)
{
char*ch;
int*w,n,i;
cout<<"输入字符集中字符的个数:
"<cin>>n;
ch=newchar[n];
w=newint[n];
cout<<"输入字符集中的字符:
"<for(i=0;icin>>ch[i];
cout<<"输入字符集中的字符的权值:
"<for(i=0;icin>>w[i];
HuffmanTreehmTree(ch,w,n);
stringstrText,strCode;
cout<<"请输入要编码的字符串";
cin>>strText;
cout<<"文本串"<";
for(intpos=0;pos{
stringstrTmp=hmTree.Encode(strText[pos]);
cout<}
cout<system("PAUSE");
cout<<"请输入要译码的二进制串";
cin>>strCode;
cout<<"编码串"<";
LinkListlkText=hmTree.Decode(strCode);
lkText.Traverse();
system("PAUSE");
return0;
}
3、测试数据
字符集中字符个数:
15
字符集中的字符:
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o
权值:
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
要编码的字符串:
abcdefghijklmno
4、测试结果
0011100011110011011010110110010101010111100111011110
七、调试分析
1.链表中的结点变量是通过指针变量来访问的。
因为在C++语言中是用P—>来表示P所指的变量,又由于结点类型是一个结构类型,因此可用P—>data和P—>next分别表示结点的数据域变量和指针域变量。
指针变量的值要么为空(NULL),不指向任何结点;要么其值为非空,即它的值是一个结点的存储地址。
注意,当P为空值时,则它不指向任何结点,此时不能通过P来访问结点,否则会引起程序错误。
八、心得体会
通过这次数据结构课程设计,使我对软件的界面设计有了一个比
较深刻的了解,对各种内部排序方法的性能有了清晰的认识,使我感觉
到到,一个优秀的软件,不仅仅是可以运行的,更应该具有人性化的界
面,协调的布局,合理的结构,良好的性能和一定的容错性一个人要完
成所有的工作是非常困难和耗时的.在以后的学习中我会更加注意各
个方面的能力的协调发展,选择一两门技术进行深入研究,成为一个既
可以统筹全局.又有一定技术专长的优秀的程序开发人员.
通过这次实验我也着实又感受了一次编程的乐趣,从中也学到了
不少知识。
虽然都说“程序=数据结构+算法”,但我在学习运用数
据结构编程之前,并没能深刻体会到这一点,直到这次课设实践。
现在编程感觉完全不同了。
在编写一个程序之前,自己能够综合考各种因素,首先选取自己需要的数据结构,是树还是图或是别的什么?
然后选定一种或几种存储结构来具体的决定后面的函数的主要风格。
最后在编写每一个函数之前,可以仔细斟酌比对,挑选出最适合当前状况的算法。
这样,即使在完整的程序还没有写出来之前,自己心中已经有了明确的原图了。
这样无形中就提高了自己编写的程序的质量。
另外,我还体会到深刻理解数据结构的重要性。
只有真正理解这样定义数据类型的好处,才能用好这样一种数据结构。
了解典型数据结构的性质是非常有用的,它往往是编写程序的关键。
我以前对递归算法一直很害怕,总是看不明白究竟这递归是怎么进行的。
在这次实验中我终于克服了这一障碍,一次次单步执行书中递归函数的例子,并一遍遍在心中自己默默的走,终于弄明白了,真的是功夫不负有心人啊!
同时我还根据自己的理解写出了类似的递归函数实现了新的功能,真是受益良多啊!
在这次实验中,我对参数的调用也进行了很多种尝试,己经能够相对准确的选择合适的参数形式来实现函数之间的数据传输交互了。
........忽略此处.......