初始有n个结点,建成的哈夫曼树将会有2*n-1个结点,每次构造都选择两棵权值最小的新节点作为孩子结点。
#include<bits/stdc++.h>
using namespace std;
int w[100];
typedef struct Huffman{
int weight;
int parent,lchild,rchild;
}HuffmanNode,HuffmanTree;
HuffmanTree t[100];//哈夫曼树
int BM[100][100];//记录哈夫曼编码
void Huffman(int n,int w[])
{
int pos1,pos2,w1,w2;
for(int i=1;i<2*n;i++) //n个结点,构建出来之后会有2n-1个结点
{
t[i].parent=t[i].lchild=t[i].rchild=0;//初始化
if(i<=n)
t[i].weight=w[i];//前n个数的权重
else
t[i].weight=0;//后n-1个数权重为0
}
for(int i=1;i<n;i++)
{
w1=w2=0x3f3f3f3f; //记录两个最小权重
pos1=pos2=0; //记录两个最小权重结点位置
for(int j=1;j<n+i;j++)
{
if(t[j].weight<w1&&t[j].parent==0)//找出最小的两个数
{
w2=w1;//更新次小值
pos2=pos1;
w1=t[j].weight;//更新最小值
pos1=j;
}
else if(t[j].weight<w2&&t[j].parent==0)//更新次小值
{
w2=t[j].weight;
pos2=j;
}
}
t[pos1].parent=t[pos2].parent=n+i;//最小的两个数的双亲就是n个数后面的结点
t[n+i].weight=w1+w2;
t[n+i].lchild=pos1;
t[n+i].rchild=pos2;
}
}
//哈夫曼编码
void BianMa(int n)
{
for(int i=1;i<=n;i++)//初始化编码数组
{
for(int j=1;j<=15;j++)//假定编码长度不超过15
BM[i][j]=-1;
}
for(int i=1;i<=n;i++)
{
int j=15;
int c=i;
int f=t[c].parent;
for(;f!=0;c=f,f=t[c].parent)
{
if(t[f].lchild==c)//如果是双亲的左孩子
BM[i][j]=0;
else//如果是双亲的右孩子
BM[i][j]=1;
j--;
}
}
}
//输出哈夫曼树
void printTree(int n,HuffmanTree t[])
{
cout<<endl<<"哈夫曼树:"<<endl<<endl;
cout<<setw(8)<<"序号"<<setw(8)<<"权值"<<setw(8)<<"左孩子"<<setw(8)<<"右孩子"<<setw(8)<<"双亲"<<endl;
for(int i=1;i<2*n;i++)
{
cout<<setw(8)<<i<<setw(8)<<t[i].weight<<setw(8)<<t[i].lchild<<setw(8)<<t[i].rchild<<setw(8)<<t[i].parent<<endl;
}
return ;
}
//输出哈夫曼编码
void printBM(int n,int w[])
{
cout<<"编码结果为:"<<endl<<endl;
cout<<setw(8)<<"权值"<<setw(14)<<"编码"<<endl;
for(int i=1;i<=n;i++)
{
cout<<setw(8)<<w[i];
cout<<" ";
for(int j=1;j<=15;j++)
{
if(BM[i][j]!=-1)
cout<<BM[i][j];
}
cout<<endl;
}
cout<<endl<<"编码结束!";
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>w[i];
Huffman(n,w);
printTree(n,t);
cout<<endl;
BianMa(n);
printBM(n,w);
return 0;
}