计算机科学与工程学院 |
程序设计基础课程设计 |
[哈夫曼编码与译码] |
|
软件084 XX |
2009-12-31 |
指导老师 :XXX、XXX
[在此处键入文档的摘要。摘要通常是对文档内容的简短总结。在此处键入文档的摘要。摘要通常是对文档内容的简短总结。] |
目录
1) 问题描述--------------------------------------------3
2) 需求分析--------------------------------------------3
3) 系统设计---------------------------------------------3
4) 编码与调试分析------------------------------------8
5) 系统使用说明---------------------------------------9
6) 测试结果---------------------------------------------10
7) 课程设计心得---------------------------------------14
8) 参考文献----------------------------------------------14
课程设计报告
课程设计题目: 《 哈夫曼编码与译码 》
一:问题描述:
问题描述为了对文件压缩,提高数据的传输或者存储,加快信息的传递,特编写此编码和译码器,提高效率,从用户的角度来说,他们可以方便的利用编码器对需要传输文件进行压缩,然后发送或者保存,当得到压缩文件后,可以利用译码器,对压缩文件的内容还原为原来内容,恢复成文件。
基本要求:该系统分为编码和译码两部分,可将编码器放在服务端,译码器放在课户端,当用户从服务端下载东西时,我们可以利用编码器将文件压缩后传输,
当压缩文件传输到客户端时,利用我们的译码器完成文件的还原。
二:需求分析:
1:编码:该部分,系统可以对从文件读出的信息进行统计,完成编码和压缩
2:译码:该部分,系统可以从压缩文件读出压缩信息,完成二叉树的建立,以及文件的还原。
3:退出
三:系统设计:
程序开始 |
编码 |
译码 |
退出 |
一个个的从文件中读取 字符,统计每个字符的个数和频率 |
利用上边得到的字符和它对应的频率,生成二叉树 |
采用递归遍历二叉树,得到字符的编码,保存起来 |
将保存好的编码用bit 来表示,减少了编码的大小 |
将我们默认的写入文件格式的数据写入文件:字符总数+不同的字符数+(不同字符数+它对应的频率)+压缩后字符的大小+文件中字符对应的压缩编码+编码中未满8bit的编码 |
依次按照默认写入的文件的的格式读出数据 |
利用读取出来的字符和它对应的频率,重建二叉树 |
遍历得到的二叉树,得到字符对应的编码,保存到一个结构数组 |
利用上边得到的字符编码,解析写入压缩文件的内容,还原文件 |
C-----编码 D-----译码 E-----退出
|
数据定义:
#define MAX_SIZE 128 //编码字符的大小
struct HuffumanNode //节点信息
{
string weight; //编码
int Frequence; //频率
char Word; //字符
bool bRet; //建树过程的判断值
HuffumanNode *pLeftChild; //左子树
HuffumanNode *pRightChild; //右子树
HuffumanNode *next; //下一个节点
HuffumanNode()
{
bRet = false;
weight = "";
Frequence = -1;
Word = NULL;
pLeftChild = NULL;
pRightChild = NULL;
next = NULL;
}
};
struct WordList //字符+频率+编码
{ //用于存储不同字符的编码信息
char sz Word;
int nFrequence;
string strWeight;
WordList()
{
nFrequence = -1;
szWord = NULL;
strWeight = "";
}
};
函数实现说明:
构造函数:HuffumanTree(); 实现数据的初始化,
int Initialization();
统计文件信息,统计文件中的字符个数和对应的频率,将不同的字符按出现的频率的大小降序排好并且保存起来
int BuildATree();
创建二叉树,通过将节点内容写入一个链表,然后,去链表的前两个组成叶子节点的方式,建立二叉树。
static int PreOrders(struct HuffumanNode *p,
struct WordList LstArray[],
string strWord,
int nDefSum);
递归遍历二叉树,并且生成字符对应的编码,保存起来。
void MemoryToFile();
写入压缩文件,按照这样的文件格式生成新文件:
未满8bit的内容 |
编码序列 |
字符和它的频率 |
不同字符个数 |
字符总的个数 |
Void Decode();
译码部分,我们首先按照我们写入文件的格式读出的字符和它的频率,然后利用这些信息,重新建一棵二叉树,通过递归遍历得到字符对应的编码,然后继续解析文件的编码序列,最终还原原文件的内容。
void InterFace();
包含对象实现过程的总的接口,这部分将类中的实现过程作了进一步的封装,它提供了编码,译码和退出,三个服务,我们通过它来完成我们的操作。
四 编码与调试:
1:当对文件操作的时候,打开文件后并且操作完成后,没有及时的关闭它,造成文件不能被写入,这个bug比较隐蔽。
2:当编码和译码同时使用一个函数来建二叉树时,之前的数据操作可能会对后边的操作带来影响,因为设计之初,没有考虑编码与译码可能会同时进行,那么就可能在通过建立链表的过程中,指针的移动会对后边造成影响,这是由于操作的指针被封装在类中,编码和译码都调用这个函数,当编码操作完后,指针的位置就不是原来的位置了,继续操作就肯定错了,我们可以通过在生成链表之前,对指针初始化,这样就能正确的处理了。
3:在处理文件压缩的过程中,由于刚开始,问题没有想清楚,仅仅是通过编码代替源文件的字符,造成文件变大,经过反复思考,发现可以通过bit 来处理这样的问题,解决的方法其实就是将编码和bit 得转换,然后将 bit 位写入文件,
处理的方法:我是采用字符串来记录编码的,然后,可以将字符串转换成bit ,
然后每八位写入,不够八位的,我们记住它们的位置和数量,直接写入,不进行压缩处理。
4:设计之初,为了简单,仅仅是将编码与译码顺序的执行,这样造成了无法将编码器与译码器分开的结果,经过改进,实现了它们的分离。
5:对特殊数据的处理,因为当文件中没有字符或者只有一个字符甚至多个字符这些极端数据的时候,程序能否正常的运行的评价它好坏的依据,也就是所谓的程序的健壮性吧,这个程序通过自己的修改,可以做到上述所有的要求.
五:使用说明:
首先:
可以选择 编码 C ,译码 D, 退出 E;
选择编码 C:输入编码文件和压缩文件名
完成压缩工作。
选择 译码:D 输入要解压的文件名和保存的文件名
完成文件的解压工作。
结束。
六:测试结果:
1:当文件中只有一个字符时:
可以看出我们没有对它进行编码,因为,一个字符,所占的空间很小,如果采取编码传输文件会变大,与我们的初衷不符,所以我采取直接传输
这是上边的解压的过程,解压成功。
2:当文件中没有内容的时候:
我们将不做任何操作,返回一个The File Is NULL..
3: 当程序既有中文又有英文的时候:
以上是这是编码文件
压缩文件
还原为原来的文件
这是原文件,压缩文件和还原的文件,他们三者的大小比较,实现了文件的压缩功能。
4:当文件中有特殊字符的时候:
同样能够完成编码与译码的工作
七:课程设计心得体会
通过这个课题的实践,使我们的动手能力得到了提高,对编码和调试以及分析程序的能力有了一定的提高,基本上领悟了哈弗曼编码和译码的原理,并且独立的完成了课题的要求,但是,没能设计出更高效的压缩算法,与 win.rar,.zip
还是有很大的差距。
八、参考文献
1:《数据结构》 王红梅
2:《离散数学》 曲婉玲
3:《C程序设计》 谭浩强