#define HuffmanCode char*
typedef struct Node* HuffmanTree;
struct Node{
int Weight;
int Parent;
int Lchild, Rchild;
};
//叶节点为n的哈夫曼树有2*n-1个节点
//用-1表示当前parent未被访问
HuffmanTree CreateHuffmanTree(int *wet, int n)
{
int i;
int Total = 2*n-1;
HuffmanTree HT = (HuffmanTree)malloc(sizeof(struct Node)*Total);
if(HT == NULL){
printf("申请内存失败");
return NULL;
}
for( i = 0; i < n; i++){//叶节点 初始化
HT[i].Parent = -1;
HT[i].Lchild = -1;
HT[i].Rchild = -1;
HT[i].Weight = *wet++; //这里是权重
}
for(i = n; i < Total; i++){//非叶节点
HT[i].Parent = -1;
HT[i].Lchild = -1;
HT[i].Rchild = -1;
HT[i].Weight = 0; //除叶节点外的 所有节点权重 置为 0
}
int min1, min2;// 用于标记每轮选出的权重最小的两个节点
for( i = n; i < Total; i++ ){
SelectMin(HT, i, &min1, &min2); //传递是i 不是n
HT[i].Lchild = min1;
HT[i].Rchild = min2;
HT[min1].Parent = i;
HT[min2].Parent = i;
HT[i].Weight = HT[min1].Weight + HT[min2].Weight;
}
return HT;
}
void SelectMin(HuffmanTree HT, int k, int *min1, int* min2)
{
//int TempMin;
int min;
int i = 0;
//int min_weight; //存放最小min 的weight 值
while(HT[i].Parent != -1)
i++;
min = i;
for(; i < k; i++ ){
if(HT[i].Weight < HT[min].Weight && HT[i].Parent == -1){
min = i;
}
}
*min1 = min;
i = 0;//需要 重新 从头部扫描
while(HT[i].Parent != -1 || i == *min1 ){//保证在本轮循环中 *min2为第二小
i++;
}
min = i;
for(; i < k; i++ ){
if(HT[i].Weight < HT[min].Weight && i != *min1 && HT[i].Parent == -1){
min = i;
}
}
*min2 = min;
//printf("*min1 = %d, *min2 = %d",*min1, *min2);
}
void HuffmanCoding(HuffmanTree HT, HuffmanCode *HC, int n)
{
HuffmanCode Head;
//HC已经声明为指针的指针了 不需要 *HC
HC = (HuffmanCode*)malloc(sizeof(char* ) * n);//指针的指针
if(HC == NULL){ //指向每一个code
printf("申请空间失败");
return ;
}//huffman编码最多需要n-1个字符 尾字符 为'\0'
char* code = (char*)malloc(sizeof(char)*n);//每一个哈夫曼编码的指针
code[n-1] = '\0';
int i;
for(i = 0; i < n; i++ ){
int current = i;
int parent = HT[i].Parent;
int start = n-1;
while(parent != -1){
if(HT[parent].Lchild == current)
code[--start] = '0';
else if(HT[parent].Rchild == current)
code[--start] = '1';
current = parent;
parent = HT[current].Parent;
}
printf("start = %d\n",start);
HC[i] = (char*)malloc(sizeof(char)*(n-start));//n-start为字符编码位数
if(HC[i] == NULL){ //多一个'\0'位
printf("申请内存失败");
return ;
}
strcpy(HC[i],&code[start]);
}
free(code);
for( i = 0; i < n; i++){
printf("HuffmanCode of %d is %s\n",HT[i].Weight, HC[i]);
}
}
int main()
{
HuffmanTree HT;
HuffmanCode HC;
int *wet, i, n;
printf("请输入节点个数:\n");
scanf("%d",&n);
wet = (int*)malloc(sizeof(int)*n);
printf("Input the weight :\n");
for(i = 0; i < n; i++ ){
scanf("%d",&wet[i]);
}
HT = CreateHuffmanTree(wet, n);// 又忘记返回值
HuffmanCoding(HT, &HC, n);
return 0;
}