数据结构课程设计实验报告Word下载.doc
- 文档编号:13181477
- 上传时间:2022-10-07
- 格式:DOC
- 页数:38
- 大小:509.50KB
数据结构课程设计实验报告Word下载.doc
《数据结构课程设计实验报告Word下载.doc》由会员分享,可在线阅读,更多相关《数据结构课程设计实验报告Word下载.doc(38页珍藏版)》请在冰豆网上搜索。
b:
0.2
c:
0.3
……
界面上,首先出现一个按钮,点击,载入conf.txt。
然后输入一个字符串,由这些字母组成。
点击按钮,显示哈夫曼编码的结果。
同时,界面上如果输入哈夫曼编码,也能被翻译成相应的字母。
如果输入格式错误,要求给予提示。
3、程序分析:
3.1存储结构
存储结构:
二叉树
示意图如下:
3.2关键算法分析
核心算法思想:
1.哈夫曼编码(HuffmanCoding)是可变字长编码。
编码时借助哈夫曼树,也即带权路径长度最小的二叉树,来建立编码。
2.哈夫曼编码可以实现无损数据压缩。
单个字符用一个特定长度的位序列替代:
在字符串中出现频率高的符号,使用短的位序列,而那些很少出现的符号,则用较长的位序列。
关键算法1:
统计字符出现的频度,记录出现的字符及其权值,对未出现的字符不予统计编码。
将统计的叶子节点编制成数组。
为创建哈夫曼树作准备。
C++实现:
for(inti=0;
str[i]!
='
\0'
;
i++) //统计频度
frequency[(short)str[i]]++;
此处以一个一维的下标表示ascII编码,以元素之表示字符频度,解决统计字符的问题。
for(intj=0;
j<
128;
j++) //统计叶子节点个数
if(frequency[j]!
=0)leaf++;
此处扫描一遍上面建立的数组得到叶子节点的个数,则由(leaf*2-1)得到总的节点个数。
关键算法2:
建立哈弗曼树——即最优二叉树。
这里实现时:
每建立一个父节点就需要扫描权值序列得到两个最小的权值。
由于节点个数逐渐增多,因而扫描次数动态变化,程序里设置计数变量来控制扫描次数的变化。
另外设置标记来标识节点是否已经被取出。
由于前面得出了总的叶子节点个数,根据哈弗曼树建立的规律可以知道总的节点数和建立哈弗曼树过程中的父子节点间的对应关系,因而可以通过下标准确定位节点,动态建立哈弗曼树。
具体C++实现参看源代码中的CreateTree()函数。
关键算法3:
建立字符编码表。
这里采用从叶子节点到根节点的顺序逆序编码,然后字符串转置得到最终编码。
while(parent!
=-1)
{
if(ptreetable[parent].lchild==child)
strcat(pcodetable[j].code,"
0"
);
//左孩子编码0
else
1"
//右孩子编码1
child=parent;
//实现递归
parent=ptreetable[child].parent;
}
此处从叶子节点向根节点编码,通过迭代法递归实现节点的查找。
strrev(pcodetable[j].code);
//字符串逆序
这里调用String类中strrev()函数实现字符串的逆序。
关键算法4:
扫描原字符串,在字符编码表中查找相应字符的编码,串接写入编码串。
i++)
{
num=0;
for(intj=0;
=pcodetable[j].ch[0];
j++,num++){;
} //查找编码表
strcat(pcode,pcodetable[num].code);
//串接编码
}
关键算法5:
解码。
这里从根节点出发,顺序查找,根据0和1的决定走左支还是右支。
当查找到叶子节点时,将字符串接写入解码字符串,并将查找点置于根节点,开始后续解码,循环直到编码后的字符串遍历完毕。
pcode[i-1]!
{
if(ptreetable[parent].lchild==-1) //找到叶子节点
{
strcat(pstr,pcodetable[parent].ch);
//串接字符
parent=leaf*2-2;
}
if(pcode[i]=='
0'
)parent=ptreetable[parent].lchild;
//走左支
else parent=ptreetable[parent].rchild;
//走右支
5、时间复杂度与空间复杂度:
1.编码和解码需要大量扫描数据,因而时间复杂度很高。
由于遍历的时候主要采用for循环结构,故主要的时间复杂度集中在此。
设不同字符的个数为n,则整个程序的时间复杂度可以累加计算,最后估算结果是:
O(3*n(n+3)/2)。
2.由于使用数组存储字符串,有一定的空间浪费,空间复杂度由初始定义的字符串最大可用长度Max和不同字符个数n决定。
计算总的空间复杂度约为O(Max*(n+4)/2+45n+20)。
6.程序运行结果
测试条件:
1.以随机输入的一串字符串。
(测试对字符的兼容能力)
2.实验题目中给出的字符串。
(测试小规模数据的编解码能力)
测试结论:
本程序对所有小规模编码能实现正确编解码
7、总结
1、哈夫曼编码的基本思想是哈弗曼树的方式来编码的这种巧妙的构思应好好体会。
2、这算是写过的最长的代码了,中间遇到了不少阻碍。
上课老师讲了实现的思想方法,但自己在将这种思想付诸实践形成代码的过程中却并非容易。
有时看老师写代码就像是说话或者说写作文一样简单,但是自己真正动手操作的时候却发现并非易事。
自己对编程语言的掌握和理解还不够透,写程序不够熟练,在算法到代码还有很长的鸿沟。
须是在今后的编程实践中勤加练习,多问多思,终有一天达到老师的水准。
3、学习哈弗曼编码是一个点,从这个点出发,可以思考很多,编码和压缩在后续课程中体现较多,应用也很广,应当扩展开去学习。
4、思考改进:
1.用数组处理字符串造成了一定的空间的浪费,后续应考虑采取其他方式处理字符串。
2.程序中对数据进行了大量的扫描和遍历,当数据量很大的时候,时间复杂度将很高,应该考虑改进哈弗曼编码。
网上应该有类似的优化的哈弗曼算法,应学习和借鉴。
8、参考文献:
1、《数据结构(C语言版)》,严蔚敏,清华大学出版社
2、《c++primer》,人民邮电出版社
9、源程序代码:
#include<
iostream.h>
iomanip.h>
string.h>
malloc.h>
stdio.h>
//typedefintTElemType;
constintUINT_MAX=1000;
charstr[50];
typedefstruct
{
intweight,K;
intparent,lchild,rchild;
}HTNode,*HuffmanTree;
typedefchar**HuffmanCode;
//-----------全局变量-----------------------
HuffmanTreeHT;
HuffmanCodeHC;
intw[50],i,j,n;
charz[50];
intflag=0;
intnumb=0;
//-----------------求赫夫曼编码-----------------------
structcou{
chardata;
intcount;
}cou[50];
intmin(HuffmanTreet,inti)
{//函数voidselect()调用
intj,flag;
intk=UINT_MAX;
//取k为不小于可能的值,即k为最大的权值1000
for(j=1;
=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&
s1,int&
s2)
{//s1为最小的两个值中序号小的那个
intj;
s1=min(t,i);
s2=min(t,i);
if(s1>
{
j=s1;
s1=s2;
s2=j;
}
//--------------算法6.12--------------------------
voidHuffmanCoding(HuffmanTree&
HT,HuffmanCode&
HC,int*w,intn)
{//w存放n个字符的权值(均>
0),构造赫夫曼树HT,并求出n个字符的赫夫曼编码HC
intm,i,s1,s2,start;
//unsignedc,f;
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)
p->
for(i=n+1;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 课程设计 实验 报告