算法分析与设计实验二哈夫曼编码.docx
《算法分析与设计实验二哈夫曼编码.docx》由会员分享,可在线阅读,更多相关《算法分析与设计实验二哈夫曼编码.docx(8页珍藏版)》请在冰豆网上搜索。
算法分析与设计实验二哈夫曼编码
算法分析与设计-实验二-哈夫曼编码
昆明理工大学信息工程与自动化学院学生实验报告
(201—201学年第一学期)
课程名称:
算法设计与分析开课实验室:
年月日
年级、专业、班
学号
姓名
成绩
实验项目名称
哈夫曼编码
指导教师
教师评语
该同学是否了解实验原理:
A.了解□B.基本了解□C.不了解□
该同学的实验能力:
A.强□B.中等□C.差□
该同学的实验是否达到要求:
A.达到□B.基本达到□C.未达到□
实验报告是否规范:
A.规范□B.基本规范□C.不规范□
实验过程是否详细记录:
A.详细□B.一般□C.没有□
教师签名:
年月日
一、上机目的及内容
1.上机内容
设需要编码的字符集为{d1,d2,…,dn},它们出现的频率为{w1,w2,…,wn},应用哈夫曼树构造最短的不等长编码方案。
2.上机目的
(1)了解前缀编码的概念,理解数据压缩的基本方法;
(2)掌握最优子结构性质的证明方法;
(3)掌握贪心法的设计思想并能熟练运用。
二、实验原理及基本技术路线图(方框原理图或程序流程图)
(1)证明哈夫曼树满足最优子结构性质;
(2)设计贪心算法求解哈夫曼编码方案;
(3)设计测试数据,写出程序文档。
数据结构与算法:
typedefchar*HuffmanCode;//动态分配数组,存储哈夫曼编码
typedefstruct
{
unsignedintweight;//用来存放各个结点的权值
unsignedintparent,LChild,RChild;//指向双亲、孩子结点的指针
}HTNode,*HuffmanTree;//动态分配数组,存储哈夫曼树
程序流程图:
三、所用仪器、材料(设备名称、型号、规格等或使用软件)
1台PC及VISUALC++6.0软件
四、实验方法、步骤(或:
程序代码或操作过程)
程序代码:
#include
#include
#include
typedefstruct
{
unsignedintweight;
unsignedintparent,LChild,RChild;
}HTNode,*HuffmanTree;//动态分配数组,存储哈夫曼树
typedefchar*HuffmanCode;//动态分配数组,存储哈夫曼编码
voidSelect(HuffmanTree*ht,intn,int*s1,int*s2)
{
inti,min;
for(i=1;i<=n;i++)
{
if((*ht)[i].parent==0)
{
min=i;
break;
}
}
for(i=1;i<=n;i++)
{
if((*ht)[i].parent==0)
{
if((*ht)[i].weight<(*ht)[min].weight)
min=i;
}
}
*s1=min;
for(i=1;i<=n;i++)
{
if((*ht)[i].parent==0&&i!
=(*s1))
{
min=i;
break;
}
}
for(i=1;i<=n;i++)
{
if((*ht)[i].parent==0&&i!
=(*s1))
{
if((*ht)[i].weight<(*ht)[min].weight)
min=i;
}
}
*s2=min;
}
//构造哈夫曼树ht,w存放已知的n个权值
voidCrtHuffmanTree(HuffmanTree*ht,int*w,intn)
{
intm,i,s1,s2;
m=2*n-1;//总的结点数
*ht=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
for(i=1;i<=n;i++)//1--n号存放叶子结点,初始化
{
(*ht)[i].weight=w[i];
(*ht)[i].LChild=0;
(*ht)[i].parent=0;
(*ht)[i].RChild=0;
}
for(i=n+1;i<=m;i++)//非叶子结点的初始化
{
(*ht)[i].weight=0;
(*ht)[i].LChild=0;
(*ht)[i].parent=0;
(*ht)[i].RChild=0;
}
printf("\n所构造的哈夫曼树为:
\n");
for(i=n+1;i<=m;i++)//创建非叶子结点,建哈夫曼树
{
Select(ht,i-1,&s1,&s2);
(*ht)[s1].parent=i;
(*ht)[s2].parent=i;
(*ht)[i].LChild=s1;
(*ht)[i].RChild=s2;
(*ht)[i].weight=(*ht)[s1].weight+(*ht)[s2].weight;
printf("%d(%d,%d)\n",(*ht)[i].weight,(*ht)[s1].weight,(*ht)[s2].weight);
}
printf("\n");
}
//从叶子结点到根,逆向求每个叶子结点对应的哈夫曼编码
voidCrtHuffmanCode(HuffmanTree*ht,HuffmanCode*hc,intn)
{
char*cd;//定义的存放编码的空间
inta[100];
inti,start,p,w=0;
unsignedintc;
hc=(HuffmanCode*)malloc((n+1)*sizeof(char*));
cd=(char*)malloc(n*sizeof(char));
cd[n-1]='\0';
for(i=1;i<=n;i++)//求n个结点对应的哈夫曼编码
{
a[i]=0;
start=n-1;//起始指针位置在最右边
for(c=i,p=(*ht)[i].parent;p!
=0;c=p,p=(*ht)[p].parent)//从叶子到根结点求编码
{
if((*ht)[p].LChild==c)
{
cd[--start]='1';
a[i]++;
}
else
{
cd[--start]='0';
a[i]++;
}
}
hc[i]=(char*)malloc((n-start)*sizeof(char));//为第i个编码分配空间
strcpy(hc[i],&cd[start]);
}
free(cd);
for(i=1;i<=n;i++)
printf("权值为%d的哈夫曼编码为:
%s\n",(*ht)[i].weight,hc[i]);
for(i=1;i<=n;i++)
w+=(*ht)[i].weight*a[i];
printf("\n带权路径长度WPL为:
%d\n\n",w);
}
voidmain()
{
HuffmanTreeHT;
HuffmanCodeHC;
int*w,i,n,wei;
printf("\t\t\t\t哈夫曼编码\n");
printf("请输入结点个数:
");
scanf("%d",&n);
w=(int*)malloc((n+1)*sizeof(int));
printf("\n请分别输入这%d个结点的权值:
\n",n);
for(i=1;i<=n;i++)
{
printf("结点%d:
",i);
fflush(stdin);
scanf("%d",&wei);
w[i]=wei;
}
CrtHuffmanTree(&HT,w,n);
CrtHuffmanCode(&HT,&HC,n);
}
五、实验过程原始记录(测试数据、图表、计算等)
六、实验结果、分析和结论(误差分析与数据处理、成果总结等。
其中,绘制曲线图时必须用计算纸或程序运行结果、改进、收获)
这次实验的内容是哈夫曼编码,哈夫曼树也就是最优二叉树,构造哈夫曼树的过程就是先在所有结点中找到权值最小的两个结点合并,依次这样找到较小的结点合并,最终生成哈夫曼树。
树中所有叶子结点的带权路径长度之和最小,带权路径长度就是该结点到树根之间的路径长度与结点上权的乘积,且权值越大的叶子离跟越近。