您的位置:首页 > 其它

Huffman树及其应用

2015-08-19 15:04 447 查看
哈夫曼树又称为最优二叉树,哈夫曼树的一个最主要的应用就是哈夫曼编码,本文通过简单的问题举例阐释哈夫曼编码的由来,并用哈夫曼树的方法构造哈夫曼编码,最终解决问题来更好的认识哈夫曼树的应用--哈夫曼编码。

一、引子

在学习中我们经常遇到将各科成绩改为优秀、良好、中等、及格和不及格。那么根据分级原理,代码表示为:

if(a<60)
b="不及格“;
elseif(a<70)
b="及格";
elseif(a<80)
b="中等";
elseif(a<90)
b="良好";
elseif(a<70)
b="优秀";



那么用二叉树表示为:

#include<iostream>
#include<stdio.h>
usingnamespacestd;

constintMAXBIT=100;
constintMAXVALUE=1000;
//创建结构体,抽象描述树节点
typedefstructHuffmanNode
{
intparent;
intlchild;
intrchild;
//结点权重
intweight;
//可以写字母等其他雷兴国
intvalue;
}stu_HuffmanNode,*pHuffmanNode;
//创建结构体,保存编码
typedefstructHuffmanCode
{
//编码的bit
intBit[MAXBIT];
intstart;
}*pHuffmanCode;

//在Huffman结点数组中找权值最小的两个结点i1和i2
voidSelectNode(pHuffmanNodeitemnode,int&MinNum1,int&MinNum2,intnum)
{
/*假设两个结点的权值*/
intMaxWeight1,MaxWeight2;
MaxWeight1=MaxWeight2=10000;
/*找出所有结点中权值最小、无父结点的两个结点*/
for(inti=0;i<num;i++)
{
//parent不为-1,就是已经判断过了。
if(itemnode[i].weight<MaxWeight1&&itemnode[i].parent==-1)
{
//将m1赋值给m2保证m1是最小的,m2是第二小的
MaxWeight2=MaxWeight1;
MinNum2=MinNum1;
MaxWeight1=itemnode[i].weight;
MinNum1=i;
}
elseif(itemnode[i].weight<MaxWeight2&&itemnode[i].parent==-1)
{
MaxWeight2=itemnode[i].weight;
MinNum2=i;
}
}
}

//创建huffman树
voidCreateHuffman(pHuffmanNodeHuffmanNodeArray,intn)
{
//创建树结点
//叶子结点(度为0)的个数为n,分支结点(度为2的n2)是n-1,二叉树没有n1,所以树结点为2*n-1;
for(inti=0;i<2*n-1;i++)
{
HuffmanNodeArray[i].weight=0;
HuffmanNodeArray[i].parent=-1;
HuffmanNodeArray[i].lchild=-1;
HuffmanNodeArray[i].rchild=-1;
HuffmanNodeArray[i].value=i;

}

//创建权值的结点,也就是在HUffman中叶子结点
for(inti=0;i<n;i++)
{
cout<<"Pleaseinputweightofleafnode"<<endl;
cin>>HuffmanNodeArray[i].weight;
}

//循环构建Huffman树,需要判断n-1次
for(inti=n;i<2*n-1;i++)
{
intminNum1=0;
intminNum2=0;
SelectNode(HuffmanNodeArray,minNum1,minNum2,i);
//minNum1,minNum2数值小于n,其实就是为叶子结点确定父节点是谁。
HuffmanNodeArray[minNum1].parent=i;
HuffmanNodeArray[minNum2].parent=i;
//创建两个叶子结点的父节点(分支结点),确定左右孩子,赋值权重
HuffmanNodeArray[i].weight=HuffmanNodeArray[minNum1].weight+HuffmanNodeArray[minNum2].weight;
HuffmanNodeArray[i].rchild=minNum1;
HuffmanNodeArray[i].lchild=minNum2;

}

}

voidCreateHuffmanCode(pHuffmanNodeitemHuffmanNode,pHuffmanCodeitemHuffmanCode,intn)
{
//获取huffman树,从叶子结点开始遍历,现找到叶子结点的父节点,如果此节点在左边就是0,否则就是1
intntemp,ptemp;
HuffmanCodephutemp;
for(inti=0;i<n;i++)
{
ntemp=i;
phutemp.start=n-1;
ptemp=itemHuffmanNode[i].parent;
//循环这个叶子结点的父节点,当父节点为-1是,就是到了树的根节点
while(ptemp!=-1)
{
if(itemHuffmanNode[ptemp].lchild==ntemp)
{
phutemp.Bit[phutemp.start]=0;
}
else
phutemp.Bit[phutemp.start]=1;
phutemp.start--;
ntemp=ptemp;
ptemp=itemHuffmanNode[ntemp].parent;
}

/*保存求出的每个叶结点的哈夫曼编码和编码的起始位*/
for(intj=phutemp.start+1;j<n;j++)
{itemHuffmanCode[i].Bit[j]=phutemp.Bit[j];}
itemHuffmanCode[i].start=phutemp.start;
}
}

//解码
voiddecodeHuffman(char*str,pHuffmanNodeitemHuffmanNode,intNum)
{
inti,tmp=0,code[1024];
intm=2*Num-1;
char*nump;
charnum[1024];
//将权值设置为0,1
for(i=0;i<strlen(str);i++)
{
if(str[i]=='0')
num[i]=0;
else
num[i]=1;
}
i=0;
nump=&num[0];
while(nump<(&num[strlen(str)]))
{
tmp=m-1;
//循环获取叶子结点在数组中序号
while(itemHuffmanNode[tmp].lchild!=-1&&itemHuffmanNode[tmp].rchild!=-1)
{
if(*nump==0)
{
tmp=itemHuffmanNode[tmp].lchild;
}
else
tmp=itemHuffmanNode[tmp].rchild;
nump++;
}
}
cout<<itemHuffmanNode[tmp].value<<endl;
}

intmain()
{
HuffmanNodeHuffmanNodeArray[100];
HuffmanCodeHuffmanCodeArray[100];
pHuffmanNodephuffman=&HuffmanNodeArray[0];
pHuffmanCodephuffmancode=&HuffmanCodeArray[0];
cout<<"输入个数"<<endl;
intn;
cin>>n;
CreateHuffman(phuffman,n);
CreateHuffmanCode(phuffman,phuffmancode,n);
for(inti=0;i<n;i++)
{
cout<<phuffmancode[i].start<<endl;
}
cout<<"输入解码符号"<<endl;
inttest;
cin>>test;
decodeHuffman("test",phuffman,n);
system("pause");
}


HuffmanTest
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: