东华理工大学软件学院软件工程系
1
数据结构课程设计报告
题目:哈夫曼编码与解码
学生姓名:侯清源
学号:1021111118
班级:102111111
指导教师:张军
2012年6月1日
东华理工大学软件学院软件工程系
2
目录
需求分析说明
总体设计
详细设计
实现部分
程序测试部分
实验总结
附图:开发环境和工程文件介绍
东华理工大学软件学院软件工程系
3
1,需求分析说明
A,通信线路中实现信息的最大传送,利用变长编码的方式,
可以有效充分利用带宽,实现信息传送前的压缩。
B,在文件保存时,利用哈夫曼编码的方式,压缩文件。可以
实现硬盘存储最大的信息量。
C,实验目的:
1,.学会使用哈夫曼进行对文本文件的编码与译码。
2,通过对哈夫曼的编码与译码,能够理解通信领域中的数据传输
的压缩原理。
3,通过对哈夫曼的编码/译码器的研究与分析,能够彻底的理解软
件设计的一般步骤和方法,灵活地运用各种数据结构进行操作,
熟练地把所学地数据结构应用地软件开发当中,提高软件设计水
平,增强程序设计能力。
D,实现功能
压缩:实现对用户输入的字符串压缩,并在终端显示相应字符对应的
频率,编码,编码长度,平均编码长度,字符个数。
并显示字符串编码后的二进制文件。
解压:实现对压缩后的二进制文件解压,还原为原来的字符串。并显
示在终端。和用户输入的字符串比较。
2,总体设计
2,1开发环境介绍
编译器:gcc4.6.3
编辑器:vim7.0附插件:ctags、taglist、autocomplpop。
打开syntaxenable、syntaxon、tnumber。
操作系统:Ubuntu12.04LTS
硬件环境:Processor:Intel(R)Core™i5-2430CPU@2.40GHz
Vendor:AcerTravelMate4750GBusinessLaptop
Memory:4G
2.2系统框架
系统结构流程
东华理工大学软件学院软件工程系
4
算法思想描述(文字和图)
1,首先,根据用户输入的字符串得到字符频率。根据频率得到频率数据,对该频率数组由
栈顶到栈低由小到大排列,同时将从小到大顺序存入优先队列
2,构造哈弗曼树,过程如下:从栈中取出两个最小频率。按照左小右大的原则。构造哈弗
曼树。同时生成父节点,即频率和。同时父节点入栈,重新按照由小到大的顺序排列。
3,重复2过程,直到栈为空。
4,编码解码的过程
编码时,根据哈弗曼树,左0右1,建立map
右边存储编码。编码时,从根节点递归遍历算法编码,左节点编码时添加0,右节点编
码添加1
解码时,也是根据哈弗曼编码树,从根节点开始,如果碰到编码的首部是1,往右遍历;
如果是0,往左遍历。直到叶子节点,遍历匹配字符成功,返回匹配的字符。同时回到
根节点,重复该步骤,翻译下一个编码。
3,详细设计
3.1,类模板设计
1,类模板设计资料:高永平老师给的资料:《数据结构(STL框架)》王晓东编
著,陈道蓄主审
2,主要是STL编程,并利用了vectormapqueue等容器,使用了容器的迭代器
iterator
东华理工大学软件学院软件工程系
5
哈夫曼树类结构模板Hafftree类模板原型
Template
Hufftree
+template
Hufftree(InputIteratorbegin,InputIteratorend);构造哈夫曼树
+~Hufftree()析构函数
+template
vector
+vector
+doubleencodelength(DataTypeconst&value);返回字符编码长度
+template
voiddecode(vector
-classNode;字符串节点类
-classNodeOrder;排序时用的类
-Node*tree;根节点
-typedefmap
encodemapencodetable;编码表
Node类成员:
template
Node
+Frequencyfreqeuency;权或频率
+Node*leftChild;左孩子指针
+union
Node*rightChild;右孩子指针
DataType*data;字符域指针
Template
NodeOrder初始化的时候对节点排序
3.2,类模板设计源代码(排版:QtCreator4.7)
Hufftree头文件
//----------------------------------------------------//
//哈夫编码与解码Haffmanencoding&decoding//
//作者:HoustarAuthorByHoustar//
//----------------------------------------------------//
#ifndefHuffman_H
#defineHuffman_H
#include
#include
#include
usingnamespacestd;
/*哈夫模板设计,需要参数:数据类型和频率*/
template
东华理工大学软件学院软件工程系
6
classHufftree
{
public:
/*输入迭代器,区间固定至begin到end,生成哈夫树*/
template
Hufftree(InputIteratorbegin,InputIteratorend);
/*析构函数,删除树*/
~Hufftree(){deletetree;}
/*哈夫编码,区间固定至begin到end*/
template
vector
/*返回单个字符的编码*/
vector
{
returnencodetable[value];
}
/*返回字符的编码长*/
doubleencodelength(DataTypeconst&value)
{
typenameencodemap::iteratoriter=(value);
returniter->();
}
/*哈夫解码,输入待解码的数组V,输出iter*/
template
voiddecode(vector
private:
classNode;//节点类
Node*tree;//指向树的指针
typedefmap
encodemapencodetable;//存储哈夫编码后的表
classNodeOrder;
};
template
structHufftree
{
Frequencyfrequency;//字符出现的频率或权
Node*leftChild;//左边孩子指针
union
{
东华理工大学软件学院软件工程系
7
Node*rightChild;//ifleftChild!=NULL如果不是叶子节点
DataType*data;//ifleftChild==NULL如果是叶子节点
};
/*节点的构造函数,通过给基类传值构造*/
Node(Frequencyf,DataTyped):
frequency(f),
leftChild(0),
data(newDataType(d))
{
}
/*构造函数,该函数用来求父节点(最小两个节点出列,同时构造父节点)入列*/
Node(Node*left,Node*right):
frequency(left->frequency+right->frequency),
leftChild(left),
rightChild(right)
{
}
/*析构函数*/
~Node()
{
if(leftChild)
{
deleteleftChild;
deleterightChild;
}
el
{
deletedata;
}
}
/*该函数对哈夫树的各个节点进行0,1编码*/
voidfill(map
vector
{
if(leftChild)//递归到叶子节点停止,叶子节点:左孩子为空
{
_back(0);//尾部加0
leftChild->fill(encodetable,prefix);//递归调用该函数
()=1;//传回最后一个数据
rightChild->fill(encodetable,prefix);//递归调用该函数
_back();//删除最后一个数据
}
el
encodetable[*data]=prefix;//将字符对应的编码存入数组的一个元素中,下
东华理工大学软件学院软件工程系
8
标由
//data确定,即data为keyword,prefix为01010的编码
}
};
/*根据权值或频率生成哈夫树*/
template
template
Hufftree
InputIteratorend):
tree(0)
{
priority_queue
FIFO
//优先队列参数说明:
//priority_queue
//其中Type为数据类型,Container为保存数据的容器,Functional为元素比较方式。
//数据类型节点类。存储容器为vector,排序方式为按权从小到大
while(begin!=end)//往优先队列添加权值二元组。
{
/*生成频率或权值的节点类,节点左边指向频率,右边指向字符*/
Node*dataNode=newNode(begin->cond,begin->first);//l.r
(dataNode);
++begin;
}
while(!())//队列不为空
{
Node*top=();//队首出列
();//清空队首
if(())//队列为空
{
tree=top;
}
el
{
Node*top2=();//队首出列
();
(newNode(top,top2));
}
}
vector
tree->fill(encodetable,bitvec);//对树的各个节点进行0,1编码
}
/*该函数主要是节点进行排序,重载了()运算符*/
东华理工大学软件学院软件工程系
9
template
structHufftree
{
booloperator()(Node*l,Node*r)
{
if(r->frequency
returntrue;
if(l->frequency
returnfal;
if(!l->leftChild&&r->leftChild)//b节点存在左孩子
returntrue;
if(l->leftChild&&!r->leftChild)//a节点存在左孩子
returnfal;
if(l->leftChild&&r->leftChild)//均存在左孩子
{
if((*this)(l->leftChild,r->leftChild))
returntrue;
if((*this)(r->leftChild,l->leftChild))
returnfal;
return(*this)(l->rightChild,r->rightChild);
}
return*(l->data)<*(r->data);
}
};
template
template
vector
InputIteratorend)
{
vector
while(begin!=end)//从第一个字符扫描到最后一个字符
{
/*从字符编码表中寻找对应字符的编码,并转换为该字符编码*/
typenameencodemap::iteratori=(*begin);
/*将该字符编码插入已完成的文件00101后面.例如aabc.已经将aa编码为11碰到
b,
编码为00.添加到编码文件尾部*/
((),i->(),i->());
++begin;
}
东华理工大学软件学院软件工程系
10
returnresult;
}
template
template
voidHufftree
OutputIteratoriter/*源码*/)
{
Node*node=tree;//指向根节点
for(vector
{
/*对二进制码和节点对应的二进制码进行比较*/
node=*i?node->rightChild:node->leftChild;
if(!node->leftChild)//比较到叶子节点则返回叶子节点对应的字符
{
*iter++=*(node->data);//将对应字符加到文件中
node=tree;//重新回到根节点,翻译下一个二进制码
}
}
}
#endif//Huffman_H
主函数文件
#include"huffman.h"
#include
#include
#include
#include
#include
#include
#include
usingnamespacestd;
map
doublesum=0;
ostream&operator<<(ostream&os,vector
{
copy((),(),ostream_iterator
returnos;
}
map
{
for(string::const_iteratoriter=();iter!=();iter++)
{
frequencies[*iter]++;
++sum;
东华理工大学软件学院软件工程系
11
}
returnfrequencies;
}
intmain(intargc,char*argv[])
{
cout<<"----SourceFile----"<
stringsource;
doublefre;
doublelenAve;
cin>>source;
frequencies=fresTable(source);
cout<<"----Encode&decodeTable----"<
Hufftree
typedeftypenamemap
cout<
<
for(ititer=();iter!=();iter++)
{
fre=iter->cond/sum;
cout<
tw(10)<
tw(10)<<(iter->first)<<
tw(10)<
tw(10)<
tw(10)<
lenAve+=fre*length(iter->first);
}
cout<
cout<
cout<<"----EncodedFile----"<
vector
cout<
cout<<"----DecodedFile----"<
stringdestination;
(encoded,back_inrter(destination));
cout<
return0;
}
4,实现部分
东华理工大学软件学院软件工程系
12
在程序调试阶段,编译不出错,运行时经常出现gmentationerror,accessviolation!
后来才知道,是自己指针操作不当,访问内存错误!用GDB调试才找出了错误。总
结,总结,再总结,绝不再次犯错误!
5,程序测试部分
5.1对英文字符编码解码
a,由用户输入英文字符串,统计频率。打印字符出现次数F,频率f,字符对应编码encode,
平均编码长lenAve。整个字符串长度Sum,平均编码长lenAve。
5.2算法改进的地方,对中文,标点等进行编码解码。
东华理工大学软件学院软件工程系
13
6,实验总结
在本次实验中,学习并深入理解了数据结构的相关设计。在本例中,对问题的深入思
考,培养了自己的创造能力,使得程序可以对任意文件编码和译码。但是对于汉字,问题的
提出如下:汉字是两个字节存储的,可是我编码的时候却只对汉字的一个字节,那么解码的
时候,会不会出现a汉字和b汉字的前半部分编码相同,这样解码的时候会出现错误?出现
错误又该如何解决?有待以后深入思考!
7,附图:开发环境和工程文件
Vim+ctag+taglist+autocomplpop
编译器和操作系统信息
东华理工大学软件学院软件工程系
14
Unubu12.04LTS桌面
工程文件介绍
huffman.h头文件
主函数cpp文件
Makefilemake文件,编译直接敲make
huffman编译好的可执行文件i686-linux平台
注意:该工程不能在VC6.0下编译,原因是VC6.0编译器不支持类
模板嵌套编译!!只能在gcc里面编译·.·
本文发布于:2022-11-22 17:16:02,感谢您对本站的认可!
本文链接:http://www.wtabcd.cn/fanwen/fan/90/481.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |