C语言实现哈夫曼树及哈夫曼编码
- 存储结构
- 查找算法
- 创建哈夫曼树
- 创建哈夫曼编码表
- 代码整合测试
存储结构
typedef struct
{
int weight;
int parent,lchild,rchild;
}HTNode,*HuffmanTree;
查找算法
void Select(HuffmanTree HT,int end,int *S1,int *S2)
{
int min1,min2;
int j,i=1;
while(HT[i].parent != 0 && i<=end)
i++;
min1 = HT[i].weight;
*S1 = i++;
while(HT[i].parent !=0 && i<=end)
i++;
if(HT[i].weight < min1)
{
min2 = min1;
*S2 = *S1;
min1 = HT[i].weight;
*S1 = i;
}
else
{
min2 = HT[i].weight;
*S2 = i;
}
for(j=i+1;j<=end;j++)
{
if(HT[j].parent != 0) continue;
if(HT[j].weight < min1)
{
*S2 = *S1;
min2 = min1;
*S1 = j;
min1 = HT[j].weight;
}
else if(HT[j].weight>=min1 && HT[j].weight<min2)
{
*S2 = j;
min2 = HT[j].weight;
}
}
}
创建哈夫曼树
void CreateHuffmanTree(HuffmanTree *HT,int n)
{
if(n<=1) return;
int m = 2*n-1;
*HT = (HuffmanTree)malloc(sizeof(HTNode)*(m+1));
for(int i=1;i<=m;++i)
{
(*HT)[i].parent = 0;
(*HT)[i].lchild = 0;
(*HT)[i].rchild = 0;
}
for(int i=1;i<=n;++i)
scanf("%d",&((*HT)[i].weight));
for(int i=n+1;i<=m;++i)
{
int S1,S2;
Select(*HT,i-1,&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;
}
}
以权值[1,2,3,4,5]为例,哈夫曼树(其一)如下:

建立以下哈夫曼树存储结构。

创建哈夫曼编码表
void CreateHuffmanCode(HuffmanTree HT,HuffmanCode *HC,int n)
{
int start,i;
*HC = (HuffmanCode)malloc(sizeof(char *)*(n+1));
char *cd = (char *)malloc(sizeof(char)*n);
cd[n-1]='\0';
for(i=1;i<=n;++i)
{
start = n-1;
int c=i;
int f=HT[i].parent;
while(f!=0)
{
--start;
if(HT[f].lchild == c) cd[start]='0';
else cd[start]='1';
c=f;
f=HT[f].parent;
}
(*HC)[i] = (char *)malloc(sizeof(char)*(n-start));
strcpy((*HC)[i],&cd[start]);
}
free(cd);
}
接着以上哈夫曼树,表如下:

运行结果:

代码整合测试
#include
#include
#include
typedef char **HuffmanCode;
typedef struct
{
int weight;
int parent,lchild,rchild;
}HTNode,*HuffmanTree;
void Select(HuffmanTree HT,int end,int *S1,int *S2)
{
int min1,min2;
int j,i=1;
while(HT[i].parent != 0 && i<=end)
i++;
min1 = HT[i].weight;
*S1 = i++;
while(HT[i].parent !=0 && i<=end)
i++;
if(HT[i].weight < min1)
{
min2 = min1;
*S2 = *S1;
min1 = HT[i].weight;
*S1 = i;
}
else
{
min2 = HT[i].weight;
*S2 = i;
}
for(j=i+1;j<=end;j++)
{
if(HT[j].parent != 0) continue;
if(HT[j].weight < min1)
{
*S2 = *S1;
min2 = min1;
*S1 = j;
min1 = HT[j].weight;
}
else if(HT[j].weight>=min1 && HT[j].weight<min2)
{
*S2 = j;
min2 = HT[j].weight;
}
}
}
void CreateHuffmanTree(HuffmanTree *HT,int n)
{
if(n<=1) return;
int m = 2*n-1;
*HT = (HuffmanTree)malloc(sizeof(HTNode)*(m+1));
for(int i=1;i<=m;++i)
{
(*HT)[i].parent = 0;
(*HT)[i].lchild = 0;
(*HT)[i].rchild = 0;
}
for(int i=1;i<=n;++i)
scanf("%d",&((*HT)[i].weight));
for(int i=n+1;i<=m;++i)
{
int S1,S2;
Select(*HT,i-1,&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;
}
}
void CreateHuffmanCode(HuffmanTree HT,HuffmanCode *HC,int n)
{
int start,i;
*HC = (HuffmanCode)malloc(sizeof(char *)*(n+1));
char *cd = (char *)malloc(sizeof(char)*n);
cd[n-1]='\0';
for(i=1;i<=n;++i)
{
start = n-1;
int c=i;
int f=HT[i].parent;
while(f!=0)
{
--start;
if(HT[f].lchild == c) cd[start]='0';
else cd[start]='1';
c=f;
f=HT[f].parent;
}
(*HC)[i] = (char *)malloc(sizeof(char)*(n-start));
strcpy((*HC)[i],&cd[start]);
}
free(cd);
}
int main()
{
int i;
int n=5;
HuffmanTree HT;
HuffmanCode HC;
CreateHuffmanTree(&HT,n);
CreateHuffmanCode(HT,&HC,n);
for(i=1;i<=n;i++)
{
printf("%d: ",HT[i].weight);
printf("%s\n",HC[i]);
}
return 0;
}