使用了自定义结构体实现了哈夫曼编码,通过输入一组权值,求出哈夫曼编码并输出每个叶子结点的编码和哈夫曼编码的总权值。
其中,使用哈夫曼树来确定每个叶子结点的编码。具体而言,定义了一个 HNode 结构体来表示哈夫曼树的结点,包括结点权值、父结点、左孩子和右孩子。
使用 findMin 函数找到权值最小的两个结点并将它们合并为一个新结点,直到只剩下根结点。然后通过 HuffCode 函数计算每个叶子结点的编码,并输出每个叶子结点的编码以及哈夫曼编码的总权值。
代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MaxSize 100
typedef struct HNode{
int weight;
int parent;
int lchild;
int rchild;
}HNode;
int findMin(HNode p[],int n){
int loc=-1,min=10000;
for(int i=1;i<=n;i++){
if(p[i].parent==0)
if(p[i].weight<min){
loc=i;
min=p[i].weight;
}
}
return loc;
}
void InitHuff(HNode tree[],int n){
int min1,min2;
while(1){
min1=findMin(tree,n);
tree[min1].parent=n+1;
min2=findMin(tree,n);
if(min2==-1){
tree[min1].parent=0;
break;
}
tree[min2].parent=n+1;
tree[n+1].parent=0;
tree[n+1].lchild=min1;
tree[n+1].rchild=min2;
tree[n+1].weight=tree[min1].weight+tree[min2].weight;
n++;
}
}
int HuffCode(HNode tree[],int n){
char *HC[n];//n个叶子结点的编码
char *code=(char *)malloc(30*sizeof(char));
code[29]='\0';
int WPL=0;
for(int i=1;i<=n;i++){
int current=i,start=29,dist=0;
while(tree[current].parent!=0){
if(current==tree[tree[current].parent].lchild)
code[--start]='0';
else code[--start]='1';
current=tree[current].parent;
dist++;
}
WPL+=dist*tree[i].weight;
HC[i]=(char *)malloc((29-start+1)*sizeof(char));
strcpy(HC[i],code+start);
}
free(code);
for(int i=1;i<=n;i++){
printf("%s\n",HC[i]);
}
return WPL;
}
int main(){
HNode tree[MaxSize];
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&tree[i].weight);
tree[i].lchild=0;
tree[i].rchild=0;
tree[i].parent=0;
}
InitHuff(tree,n);
int WPL=HuffCode(tree,n);
printf("%d",WPL);
return 0;
}