#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define N 7
typedef struct {
int weight;
int parent;
int lchild;
int rchild;
}HTNode,*HuffmanTree;
typedef char ** HuffmanCode;
//找出数组中权值最小的两个节点下标,分别用s1和s2保存
void Select( HuffmanTree HT,int n,int &s1,int &s2)
{
int i;
s1 = s2 = 0;
int min1 = 100;//最小值
int min2 = 80;//次小值
for ( i = 1; i <= n; ++i )
{
if ( HT[i].parent == 0 )
{//筛选没有父节点的最小和次小权值下标
if ( HT[i].weight < min1 )
{//如果比最小值小
min2 = min1;
s2 = s1;
min1 = HT[i].weight;
s1 = i;
}
else if ( (HT[i].weight >= min1) && (HT[i].weight < min2) )
{//如果大于等于最小值,且小于次小值
min2 = HT[i].weight;
s2 = i;
}
}
}
}
void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n)
{
int m=2*n-1;
int s1,s2;
int i,c,f,j;
char *code;
HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); //0号单元未使用
HuffmanTree p;
for ( i = 1; i <= n; i++ )
{
HT[i].weight=w[1];
HT[i].parent=0;
HT[i].lchild=0;
HT[i].rchild=0;
}
for ( i = n + 1; i <= m; i++ )
{
HT[i].weight=0;
HT[i].parent=0;
HT[i].lchild=0;
HT[i].rchild=0;
}
for(i=n+1;i<=m;i++)//build huffmantree
{
Select(HT,i-1,s1,s2);//在HT[1...i-1]选择parent为0且weight最小的两个节点,其序号分别为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;
}
//---从叶子到根逆向求每个字符的哈夫曼编码---
HC=(char **)malloc(n*sizeof(char *));
code=(char *)malloc(n*sizeof(char));//使用了第0个单元
for(i=1;i<=n;i++)
{
for(c=i,f=HT[c].parent,j=0;f!=0;c=HT[c].parent,f=HT[c].parent,j++)
{//从叶子扫描到根
if(HT[f].lchild==c)
{
code[j]='0';
}
else if(HT[f].rchild==c)
{
code[j]='1';
}
}
code[j]=' ';
HC[i]=(char *)malloc(strlen(code)*sizeof(char));
strcpy(HC[i],code);
}
}
int main()
{
int i;
char key[N]={'0','A','B','C','D','E','F'};//第0个元素保留不用
int w[N]={0,1,2,3,4,6,8}; //第0个元素保留不用
HuffmanTree HT;
HuffmanCode HC;
HuffmanCoding(HT,HC,w,N-1);
for(i=1;i<N;i++)
printf("%c:%s
",key[i],HC[i]);
printf("
");
return 0;
}