数据结构实验二哈夫曼树及哈夫曼编码译码的实现Word格式文档下载.docx
- 文档编号:19276334
- 上传时间:2023-01-05
- 格式:DOCX
- 页数:8
- 大小:164.36KB
数据结构实验二哈夫曼树及哈夫曼编码译码的实现Word格式文档下载.docx
《数据结构实验二哈夫曼树及哈夫曼编码译码的实现Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《数据结构实验二哈夫曼树及哈夫曼编码译码的实现Word格式文档下载.docx(8页珍藏版)》请在冰豆网上搜索。
(3)学习利用树求解实际问题
二、实验内容和原理
定义哈夫曼树的存储结构;
输入要编码的字符权重,根据权重建立哈夫曼树,并进行编码,最后输出哈夫曼编码。
三、实验环境
硬件:
(1)学生用微机
(2)多媒体教室或远程教学(3)局域网环境
软件:
(1)WindowsXP中文操作系统
(2)TurboC3.0
四、算法描述及实验步骤
1.算法描述
(1).建立哈夫曼树的算法
定义各节点类型其中应包含两类数据
一是权重域weight;
一是指针域而指针域中应该包括指向左右孩子和指向双亲的指针这里分别用lchild、rdhild和parent来表示因此可用静态三叉链表来实现,在实际构造中由于是叶子节点来构造新的根节点其构造过程中仅与叶子节点的权重有关而与其数据域无关所以构造过程中不用考虑其数值域,并且在链表中从叶子开始存放,让后不断的将两颗最小权值的子树合并为一颗权值为其和的较大的子树,逐步生成各自内部节点直到树根。
(2).哈夫曼编码的算法
将建立的哈夫曼树从每个叶子节点开始沿着双亲域回到根节点,梅走一步进行编码得到一位编码值;
由于每个叶子节点的哈夫曼编码是从根节点到相应的叶子的路径的各个分支的代码组成的0和1序列,所以先得到了低位编码后得到高位编码因此可用一维数组从后向前来存放各位编码值,并用start来记录编码的起始位置。
2.算法流程图
构建哈夫曼树算法流程
哈夫曼编码算法流程
3.代码
仅作参考--redbatzero
#include<
stdio.h>
malloc.h>
#definemaxvalue10000//定义最大权值常量
#definemaxnodenumber100//定义节点最大数
#definemaxbit10//定义哈弗曼编码最大长度
typedefstruct//定义新数据类型即节点结构
{intweight;
//权重域
intparent,lchild,rchild;
//指针域
}htnode;
//节点类型标识符
//typedefhtnode*huffmanstree;
//定义哈弗曼数类型
htnodeht[maxnodenumber];
//定义三叉链表存储数组
typedefstruct//定义保存一个叶子节点哈弗曼编码的结构
{
intbit[maxbit];
//定义一维数组为编码域
intstart;
//定义位置域
}hcnodetype;
//定义编码类型
htnode*creatstree(intn)//huffmanstreecreatstree(intn)//建立哈夫曼树算法实现函数
inti,j,m1,m2,k1,k2;
//局部变量
for(i=0;
i<
2*n-1;
i++)//初始化各节点
{
ht[i].weight=0;
//权重初始化为0
ht[i].parent=-1;
//根节点和给左右孩子初始化为-1
ht[i].lchild=-1;
ht[i].rchild=-1;
}
n;
i++)//权重赋初值,由用户输入
scanf("
%d"
&
ht[i].weight);
n-1;
i++)//生成新节点构造哈夫曼树
m1=maxvalue;
//预置最小权值变量为最大权值
m2=maxvalue;
//预置次小权值变量为最大权值
k1=0;
//预置最小权值节点位置为下标为0处
k2=0;
//预置次小权值节点位置为下标为0处
for(j=0;
j<
n+i;
j++)//循环找出每趟最下权值和所在位置
if(ht[j].parent==-1&
&
ht[j].weight<
m1)
{
m2=m1;
k2=k1;
m1=ht[j].weight;
k1=j;
}
else//当小于当前次小m2则更新m2及其位置
if(ht[j].parent==-1&
m2)
{
m2=ht[j].weight;
k2=j;
}
ht[k1].parent=n+i;
//修改最小权值节点的双亲为刚生成的新节点
ht[k2].parent=n+i;
//修改次小权值节点的双亲为刚生成的新节点
ht[n+i].weight=ht[k1].weight+ht[k2].weight;
//将新生成的权重值填入新的根节点
ht[n+i].lchild=k1;
//新生节点左孩子指向k1
ht[n+i].rchild=k2;
//新生节点右孩子指向k2
returnht;
//返回哈夫曼树指针
}
voidgetstree(htnode*ht,intn)//哈夫曼编码算法及打印函数的实现
inti,j,c,p;
//局部变量的定义
hcnodetypecd[maxnodenumber];
//定义存储哈夫曼编码的数组
i++)//循环控制对每一个节点进行编码
c=i;
//为编码各节点初始化c和j
j=maxbit;
do
{
j--;
//j指向bit中存放编码为的正确位置
p=ht[c].parent;
//p指向c的双亲节点
if(ht[p].lchild==c)//如果c是p的左孩子
cd[i].bit[j]=0;
//编码为赋值0
else//否则即c是p的右孩子
cd[i].bit[j]=1;
//编码赋值1
c=p;
//更新当前指针,为下一节点编码做准备
}while(ht[p].parent!
=-1);
//判断是否编码结束即循环至最终根节点
cd[i].start=j;
//编码完成,记下编码开始位置
i++)//循环打印各节点哈夫曼编码
for(j=cd[i].start;
maxbit;
j++)//循环逐一输出
printf("
cd[i].bit[j]);
\n"
);
//每输出一编码后换行
intmain()//主函数
intn;
printf("
请输入节点数:
"
//用户输入节点数
scanf("
n);
htnode*p;
//huffmanstreep//定义哈夫曼树类型p
p=(htnode*)malloc(sizeof(htnode*));
//p=(huffmanstree)malloc(sizeof(huffmanstree))//分配内存空间
p=creatstree(n);
//调用建立哈夫曼树函数赋返回值给p
getstree(p,n);
//调用编码函数读入建立的哈夫曼树p进行编码
return0;
五、调试过程
出现该错误是因为type识别不了,即定义哈夫曼树时确切的说是type并不能定义htnode*标识符为huffmanstree:
typehtnode*huffmanstree
这个小错误可以通过连个方法来修改一是将type改为typedef,当然直接删除该定义完全不会影响程序的执行,但在定义建立哈夫曼树函数时返回值应直接用htnode*;
该错原因是参数未能成功传递,其中的ht[p]系统当做是未定义的类型可知,在getstree(htnodeht,intn)时正确的应当是传递哈夫曼树的头指针即数组首地址ht因此改为getstree(htnode*ht,intn)
六、实验结果
通过改正后成功编译连接,进行数据测试
{5,20,12,7,47,9}当然编码因为定义时大小的左右排序是不同的所以编码也不唯一,但在这里是以左小右大来分布的,所以编码结果符合预期的。
所构造哈夫曼树如图所示
七、总结
该实验不仅让我加深了对哈夫曼树的理解,更是让我惊叹该算法的强大,一个简单的数组类型数据加之简单的链表在实现该算法后让我理解了基础理论知识的重要性,倘若在不知道这个算法的情况下。
我不知道自己得花多少的时间来实现编码,或许最终还不一定能够很好的实现编码,更别说优化了。
尤其树的基本存储方法更加深了我对树的理解。
附录:
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 实验 二哈夫曼树 哈夫曼 编码 译码 实现
![提示](https://static.bdocx.com/images/bang_tan.gif)