哈弗曼树定义:给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。
哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。
#include<iostream>
#include<iomanip>
using namespace std;
const int n=7; //maxn表示叶子数目
const int m=2*n-1; //m为森林中树的数
const int maxValue=3555; //最大权值
struct TreeNode //哈夫曼树中的一个结点
{ float weight; //权值
int parent; //双亲
int lchild,rchild; //左孩子、右孩子
};
struct hacode //哈弗曼编码
{ int bits[n+1]; //哈弗曼编码
int start; //编码的存放位置
char ch; //所对应的字符
};
TreeNode haffTreeNode[m+1];
hacode code[n+1];
void CreatHaffTreeNode() //建立哈夫曼树
{
int i,j,p1,p2; float s1,s2;
for(i=1;i<=2*n-1;i++)
{
haffTreeNode[i].parent=0;
haffTreeNode[i].lchild=0;
haffTreeNode[i].rchild=0;
haffTreeNode[i].weight=0;
}
cout<<"请输入"<<n<<"个权值"<<endl;
for(i=1;i<=n;i++)
cin>>haffTreeNode[i].weight; //输入权值
for(i=n+1;i<=2*n-1;i++) //进行N-1次合并,n-1个非叶子节点
{ p1=p2=0; //p1,p2分别指向两个权值最小的值的位置
s1=s2=maxValue; //s1,s2代表两个最小权值
for(j=1;j<=i-1;j++){ //选两个最小值
if(haffTreeNode[j].parent==0) //该权值还没有选中
if(haffTreeNode[j].weight<s1)
{
s2=s1;
s1=haffTreeNode[j].weight;
p2=p1;
p1=j;
}
else if(haffTreeNode[j].weight<s2)
{
s2=haffTreeNode[j].weight;
p2=j;
}
}//以下为合并
haffTreeNode[p1].parent=i;
haffTreeNode[p2].parent=i;
haffTreeNode[i].lchild=p1;
haffTreeNode[i].rchild=p2;
haffTreeNode[i].weight=haffTreeNode[p1].weight+haffTreeNode[p2].weight;
}
}
//带权路径长度:哈法曼树的除叶子节点,剩余的节点的权值之和
float WPL()
{
float wpl=0;
for(int i=2*n-1;i>=n+1;i--)
wpl=wpl+haffTreeNode[i].weight;
return wpl;
}
void HuffCode() //哈弗曼编码
{
hacode cd;
int c,p;
for(int i=1;i<=n;i++)
{
cd.start=n+1;
cd.ch=96+i; //第一个树叶对应字母a,其余依此类推
c=i;
p=haffTreeNode[i].parent;
while(p!=0)
{
cd.start--;
if(haffTreeNode[p].lchild==c)
cd.bits[cd.start]=0;
else
cd.bits[cd.start]=1;
c=p;
p=haffTreeNode[p].parent;
}
code[i]=cd;
}
for(int i=1;i<=n;i++)
{
cout<<"字符"<<code[i].ch<<"的权值为:"<<haffTreeNode[i].weight<<setw(5)<<" 编码为:";
for(int j=code[i].start;j<=n;j++)
cout<<code[i].bits[j]<<" ";
cout<<endl;
}
}
void TransCode() //哈弗曼译码
{
int i=m;
char b;
cout<<"请输入二进制编码串(以非0,1结束)"<<endl;
cin>>b;
while((b=='0')||(b=='1'))
{
if(b=='0')
i=haffTreeNode[i].lchild;
else
i=haffTreeNode[i].rchild;
if(haffTreeNode[i].lchild==0)
{
cout<<code[i].ch;
i=m;
}
cin>>b;
}
}
void main()
{
CreatHaffTreeNode(); //建立哈夫曼树
float length=WPL();
cout<<"长度是:"<<length<<endl;
HuffCode(); //实现哈弗曼编码
TransCode(); //进行哈弗曼译码
cout<<endl;
system("pause");
}