北邮数据结构实验三题目2哈夫曼树文档格式.docx
- 文档编号:18226160
- 上传时间:2022-12-14
- 格式:DOCX
- 页数:19
- 大小:224.90KB
北邮数据结构实验三题目2哈夫曼树文档格式.docx
《北邮数据结构实验三题目2哈夫曼树文档格式.docx》由会员分享,可在线阅读,更多相关《北邮数据结构实验三题目2哈夫曼树文档格式.docx(19页珍藏版)》请在冰豆网上搜索。
测试数据:
IlovedataStructure,IloveComputer。
IwilltrymybesttostudydataStructure.
提示:
1、用户界面可以设计为“菜单”方式:
能够进行交互。
2、根据输入的字符串中每个字符出现的次数统计频度,对没有出现的
字符一律不用编码。
2.程序分析
2.1存储结构
二叉树:
示意图:
root
lchildparentrchild
(静态三叉链表存储)
weight
LChild
RChild
parent
2
-1
1
3
6
9
4
5
(a)初始化哈夫曼树
11
20
(b)创建好的哈夫曼树
哈夫曼编码的存储结构
data
code
0
Z
100
1
C
101
2
B
11
3
A
01
2.2关键算法分析
1初始化
算法步骤:
①统计字符串字符综述并申请动态数组存储字符串;
②对所存储字符串进行排序;
③统计不同字符的个数;
④释放动态内存空间;
⑤创建哈夫曼数的数组;
⑥创建哈夫曼编码表。
源代码:
voidHuffman:
:
Init(char*s)
{
intn=0;
while(*(s+n)!
='
\0'
)
{
n++;
//统计字符串字符数
}
char*temp=newchar[n];
//申请动态数组存储字符串以便之后对字符串排序
for(inti=0;
i<
n;
i++)
temp[i]=*(s+i);
charctemp;
n-1;
i++)//冒泡排序法,排序以后方便统计不同字符串出现的个数
for(intj=0;
j<
n-1-i;
j++)
{
if(temp[j]>
temp[j+1])
{
ctemp=temp[j];
temp[j]=temp[j+1];
temp[j+1]=ctemp;
}
}
intk=1;
for(inti=1;
i++)//统计不同字符个数
if(temp[i]!
=temp[i-1])
k++;
HTree=newHNode[2*k-1];
m=2*k-1;
//存储哈夫曼数组大小
intl=0;
//统计不同字符出现的频度
k=0;
//控制哈夫曼数组下标
ctemp=temp[0];
//做标记
if(temp[i]==ctemp)
l++;
if(i==n-1)
HTree[k].weight=l;
else
HTree[k].c=ctemp;
HTree[k].weight=l;
ctemp=temp[i];
l=1;
delete[]temp;
//释放动态内存空间
Creat();
//创建哈夫曼数的数组
CodeTable();
//创建哈夫曼编码表
}
时间复杂度:
n
2创建哈夫曼树动态数组
①根据权重数组初始化哈夫曼树;
②选取权值最小的两个结点作为左右子树,构成一个新的二叉树,其根结点的权值取左右子树权值之和;
③删除这两棵子树,将新构成的树加入到T中,重复②③直至T中只含有一棵树。
Creat()
intn=(m+1)/2;
//n表示不同字符的个数
HTree[i].LChild=-1;
HTree[i].RChild=-1;
HTree[i].parent=-1;
intx,y;
for(inti=n;
2*n-1;
SelectMin(x,y,i);
//找出最小权重的两个字符
HTree[x].parent=i;
HTree[y].parent=i;
HTree[i].weight=HTree[x].weight+HTree[y].weight;
HTree[i].LChild=x;
HTree[i].RChild=y;
3寻找权值最小的两个数
①首先判断根结点是否是最小,若不是,则继续判断;
②依次对各个结点进行判断,找出最小结点;
③找出最小权重结点后将最小节点放置在无法再次访问的位置,再进行次小值的判断。
SelectMin(int&
x,int&
y,inti)
x=0;
while(HTree[x].parent!
=-1)//防止第一个就是之前找到的最小的导致下面循环无效
x++;
for(intj=1;
i;
if(HTree[j].parent!
=-1)
continue;
x=(HTree[x].weight<
=HTree[j].weight)?
x:
j;
HTree[x].parent=-2;
//防止y重复
y=0;
while(HTree[y].parent!
y++;
y=(HTree[y].weight<
y:
4生成哈夫曼编码表
①申请与不同字符个数对应的动态空间,以存储不同字符代表的编码;
②自下而上判断,左孩子则编码'
0'
,右孩子则编码'
1'
,到达根节点之后结束循环;
③字符编码串最后添加结束符,结束编码;
④颠倒字符串。
CodeTable()
HcodeTable=newHCode[n];
//申请与不同字符个数对应的动态空间,以存储不同字符代表的编码
HcodeTable[i].data=HTree[i].c;
intchild=i;
intparent=HTree[i].parent;
//用于判断
intk=0;
while(parent!
=-1)//自下而上到达根节点之后结束循环
if(child==HTree[parent].LChild)//左孩子则编码'
HcodeTable[i].code[k]='
;
else
//右孩子则编码'
child=parent;
parent=HTree[child].parent;
HcodeTable[i].code[k]='
//字符编码串最后添加结束符
Reverse(HcodeTable[i].code);
//由于自上而下因此需要颠倒字符串
5颠倒字符串
①统计字符串字符个数;
②将第i个字符与第n-i个进行交换。
Reverse(charc[])
chartemp;
while(c[n+1]!
)//统计字符个数
=n/2;
temp=c[i];
c[i]=c[n-i];
c[n-i]=temp;
6编码函数
①将输入的字符串与编码表中的比较,字符串尾停止,如果相等,则对字符进行编码,并对每个字符的编码进行输出;
②编码的同时统计编码的总字节数;
③计算哈夫曼编码压缩比。
Encode(char*s,string*d)
floatsum=0;
//统计字节数
while(*s!
for(inti=0;
(m+1)/2;
if(*s==HTree[i].c)
cout<
<
HcodeTable[i].data<
"
"
HcodeTable[i].code<
endl;
for(intj=0;
HcodeTable[i].code[j]!
{
*d+=HcodeTable[i].code[j];
sum+=1;
}
s++;
n++;
break;
cout<
压缩比为:
sum/(8*n)<
7解码函数
①从根节点开始进行解码,如果字符为0,则为左孩子,1,则为右孩子;
②编码匹配编码表中对应的数据,进行解码。
Decode(char*s,char*d)
while(*s!
intparent=m-1;
//根结点
while(HTree[parent].LChild!
=-1)//从根节点开始直到终端结点结束循环
if(*s=='
parent=HTree[parent].LChild;
parent=HTree[parent].RChild;
if(*s=='
)//不解码码串最尾部,没有编码的部分
return;
s++;
*d=HcodeTable[parent].data;
d++;
2.3其他
1判断最小权值的函数还可以简化为一个循环;
2没有直观地画出哈夫曼树,用户只能通过哈夫曼编码表进行解码。
3.程序运行结果
1、测试主函数流程
12
2测试结果如图
4.总结
1、出现的问题及解决办法
编写最小权值函数时,寻找到的最小值是一样的,原因是寻找次小值的过程中,重复了寻找最小值的过程,造成重复,之后在寻找到最小值后将其父结点更改,使接下来的寻找过程不再考虑它
2、心得体会
进一步了解哈夫曼树的思想和相关概念,锻炼了使用二叉树解决实际问题的能力
3、下一步的改进
将查找权值最小的两个数的函数由2个循环改进为一个循环,简便算法;
直观地画出哈夫曼树,使用户更加清晰地认识编码结构。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 实验 题目 哈夫曼树
![提示](https://static.bdocx.com/images/bang_tan.gif)