哈夫曼编码.docx
《哈夫曼编码.docx》由会员分享,可在线阅读,更多相关《哈夫曼编码.docx(12页珍藏版)》请在冰豆网上搜索。
哈夫曼编码
《数据结构》实验报告
实验名称:
构造哈夫曼树与哈夫曼树编码
专业:
计算机科学与技术
班级:
1001
姓名:
学号:
完成日期:
20年月日
2012年12月6日
1、问题描述
哈夫曼树:
给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffmantree)。
哈夫曼编码:
哈夫曼编码(HuffmanCoding)是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。
Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫作Huffman编码。
2、详细设计
1、构造哈夫曼树
在构造哈夫曼树时,可以设置一个结构数组HuffNode保存哈夫曼树中各节点的信息,根据二叉树的性质可知,具有n个结点的哈夫曼树共有2n-1个结点,所以数组HuffNode的大小设置为2n-1,数组元素的结构形式如下:
Weightlchildrchilepraent
其中,weight域保存结点权值,lchild和rchild域分别保存该节点的左孩子和右孩子结点在数组HuffNode中的序号,从而建立起结点之间的关系,为了判定一个结点是否已加入到要建立的哈夫曼树中,可通过parent域的值来确定,初始时,parent值为-1,当结点加入到树中时,该结点parent的值为其双亲结点在数组HuffNode中的序号,就不会是-1了。
哈夫曼树代码:
#include
#defineMAXVALUE100
#defineMAXLEAF30
#defineMAXNODEMAXLEAF*2-1
typedefstruct
{
intweight;
intparent;
intlchild;
intrchild;
}HNodeType;
voidHaffmanTree(HNodeTypeHuffNode[]);
voidPrint(HNodeTypeHuffNode[]);
intmain()
{
HNodeTypep[MAXLEAF];
HaffmanTree(p);
Print(p);
return0;
}
/*-----------------------endmain----------------------------*/
voidHaffmanTree(HNodeTypeHuffNode[])
{
/*哈弗曼树的构造算法*/
inti,j,m1,m2,x1,x2,n;
printf("请输入叶节点的个数:
");
scanf("%d",&n);/*输入叶节点的个数*/
for(i=0;i<2*n-1;i++)/*数组HuffNode[]初始化*/
{
HuffNode[i].weight=0;
HuffNode[i].parent=-1;
HuffNode[i].lchild=-1;
HuffNode[i].rchild=-1;
}
printf("请输入%d个叶节点的权值:
",n);
for(i=0;i{
scanf("%d",&HuffNode[i].weight);
}
for(i=0;i{
m1=MAXVALUE;
m2=MAXVALUE;
x1=x2=0;
for(j=0;j{
if(HuffNode[j].weight{
m2=m1;
x2=x1;
m1=HuffNode[j].weight;
x1=j;
}
elseif(HuffNode[j].weight{
m2=HuffNode[j].weight;
x2=j;
}
}
/*将找出的两颗子树合并为一颗子树*/
HuffNode[x1].parent=n+i;
HuffNode[x2].parent=n+i;
HuffNode[n+i].weight=HuffNode[x1].weight+HuffNode[x2].weight;
HuffNode[n+i].lchild=x1;
HuffNode[n+i].rchild=x2;
}
}
voidPrint(HNodeTypeHuffNode[])//输出哈夫曼树
{
inti=0;
printf("%10s%10s%10s%10s\n","weight","parent","lchild","rchild");
do
{
printf("%10d%10d%10d%10d\n",HuffNode[i].weight,HuffNode[i].parent,HuffNode[i].lchild,HuffNode[i].rchild);
i++;
}while(HuffNode[i].parent>=-1);
}
2、哈夫曼编码
哈夫曼编码实质上是在已建立在哈夫曼树中,从叶节点开始,沿结点的双亲链域回退到根节点,每回退一步,就走过了哈夫曼树的一个分支,从而得到一位哈夫曼码值,由于一个字符的哈夫曼是从根节点到相应的叶节点所经过的路径上各分支所组成的0、1序列,因此先得到的分支代码为所求编码的低位码,后得到的分支代码为所求编码的高位码,可以设置一结构数组HuffCode,用来存放各字符的哈夫曼编码信息,数组元素的结构如下:
Bitstart
其中,分量bit为一维数组,用来保存字符的哈夫曼编码;start表示该编码在数组bit中的开始位置,所以对于第i个字符,它的哈夫曼编码存放在HuffCode[i].bit中的HuffCode[i].start到n的分量上。
哈夫曼编码代码:
#include
#defineMAXVALUE100//定义最大权值
#defineMAXLEAF30//定义哈夫曼树的中叶节点个数
#defineMAXNODEMAXLEAF*2-1
#defineMAXBIT10//定义哈夫曼编码的最大长度
intn;
typedefstruct
{
intweight;
intparent;
intlchild;
intrchild;
}HNodeType;
typedefstruct
{
intbit[MAXBIT];
intstart;
}HCodeType;
voidHaffmanTree(HNodeTypeHuffNode[]);
voidHaffmanCode();
voidPrint(HNodeTypeHuffNode[]);
intmain()
{
HaffmanCode();
return0;
}
/*-----------------------endmain----------------------------*/
voidHaffmanTree(HNodeTypeHuffNode[])
{
/*哈弗曼树的构造算法*/
inti,j,m1,m2,x1,x2;
printf("请输入叶节点的个数:
");
scanf("%d",&n);/*输入叶节点的个数*/
for(i=0;i<2*n-1;i++)/*数组HuffNode[]初始化*/
{
HuffNode[i].weight=0;
HuffNode[i].parent=-1;
HuffNode[i].lchild=-1;
HuffNode[i].rchild=-1;
}
printf("请输入%d个叶节点的权值:
",n);
for(i=0;i{
scanf("%d",&HuffNode[i].weight);
}
for(i=0;i{
m1=MAXVALUE;
m2=MAXVALUE;
x1=x2=0;
for(j=0;j{
if(HuffNode[j].weight{
m2=m1;
x2=x1;
m1=HuffNode[j].weight;
x1=j;
}
elseif(HuffNode[j].weight{
m2=HuffNode[j].weight;
x2=j;
}
}
/*将找出的两颗子树合并为一颗子树*/
HuffNode[x1].parent=n+i;
HuffNode[x2].parent=n+i;
HuffNode[n+i].weight=HuffNode[x1].weight+HuffNode[x2].weight;
HuffNode[n+i].lchild=x1;
HuffNode[n+i].rchild=x2;
}
}
voidHaffmanCode()
{
//生成哈夫曼编码
HNodeTypeHuffNode[MAXNODE];
HCodeTypeHuffCode[MAXLEAF],cd;
inti,j,c,p;
HaffmanTree(HuffNode);//建立哈夫曼树
Print(HuffNode);//输出哈夫曼树
for(i=0;i{
cd.start=n-1;
c=i;
p=HuffNode[c].parent;
while(p!
=-1)//由叶节点向上直到树根
{
if(HuffNode[p].lchild==c)
cd.bit[cd.start]=0;
else
cd.bit[cd.start]=1;
cd.start--;
c=p;
p=HuffNode[c].parent;
}
for(j=cd.start+1;j//保存求出的每个叶节点的哈夫曼编码和编码的起始位
HuffCode[i].bit[j]=cd.bit[j];
HuffCode[i].start=cd.start;
}
printf("所求的哈夫曼编码为:
\n");
for(i=0;i{
for(j=HuffCode[i].start+1;j//输出每个叶节点的哈夫曼编码
printf("%ld",HuffCode[i].bit[j]);
printf("\n");
}
}
voidPrint(HNodeTypeHuffNode[])//输出哈夫曼树
{
inti=0;
printf("所求的哈夫曼树为:
\n");
printf("%10s%10s%10s%10s\n","weight","parent","lchild","rchild");
do
{
printf("%10d%10d%10d%10d\n",HuffNode[i].weight,HuffNode[i].parent,HuffNode[i].lchild,HuffNode[i].rchild);
i++;
}while(HuffNode[i].parent>=-1);
}
三、测试分析
测试时以5个结点进行测试,且权值都设为1.
1、构造哈夫曼树运行结果截图:
构造的哈夫曼树为:
2、哈夫曼编码结果截图:
可知编码分别为:
110111000110