C语言利用哈夫曼树实现哈夫曼树生成和哈夫曼编码的实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MaxSize 50
#define MAX 32767
   /* int 8位整数*/
typedef struct{
    char c;                       /* 字符;  */
    int w;                        /* 字符权值;  */
    char *code;                   /*字符的Huffman编码;  */
}HuffmanCode[MaxSize];

typedef struct{
    int weight;                   /* 权值;  */
    int lchild,rchild,parent;
}HTNode,HuffmanTree[MaxSize];

/* ================================================================================  */
void CreateHuffmanTree(HuffmanTree HT,int length,HuffmanCode hc);        /* 生成Huffman树;  */
void SelectHTNode(HuffmanTree HT,int n,int *min1,int *min2);    /* 查找最小和次小序号;  */
void HuffmanCoding1(HuffmanTree HT,int n,HuffmanCode hc);            /* 生成Huffman编码;  */

/* ================================================================================  */
int main()
{
    HuffmanTree HT;       /* Huffman树;  */
    HuffmanCode HC;       /* Huffman编码;  */

    int i,n;
    printf("--------HuffmanCode--------\n");
    printf("\nPlease input the number of char:");
    scanf("%d",&n);
    system("cls");
    printf("the number of char: %2d\n\n",n);
    printf("Input the char and its weight: (e.g.:  \"a16[enter]\" ): \n");
    for(i=1;i <= n;i++)
    {
        while(getchar() != '\n')    NULL;
        printf("No.%2d:  ",i);
        HC[i].c = getchar();
        scanf("%d",&HC[i].w);
    }
    CreateHuffmanTree(HT,n,HC);
    HuffmanCoding1(HT,n,HC);

    printf("\nOutput the Huffman Code:\n");
    for(i = 1;i<=n;i++)
    {
        printf("\n %c :",HC[i].c);
        puts(HC[i].code);
    }
/* 测试Huffman树结构;  */
    printf("\n\nOutput the structure of Huaffman tree:");system("pause");
    printf("\nHT[i]:\tweight\tparent\tLchild\tRchild\n");
    for(i = 1;i<2*n;i++)
    {
        if(i <= n)    printf("(%c)",HC[i].c);
        printf("%2d:\t %2d;\t%2d,\t %2d,\t %2d.\n", i,HT[i].weight,HT[i].parent,HT[i].lchild,HT[i].rchild);
    }
    getch();
    return 0;
}


/* ================================================================================  */
void CreateHuffmanTree(HuffmanTree HT,int length,HuffmanCode HC)       /* Huffman树初始化;  */
{
    int i;
    int min1,min2;//最小的两个权值

    HT[0].weight = MAX;//哈夫曼树丛0开始储存权值
    
    /*先把叶子节点的双亲,左右变量全部赋值为0*/
    for(i = 1;i <= length;i++)
    {
        HT[i].weight = HC[i].w;//哈夫曼编码里的权值,赋值给哈夫曼树里面的权值
        HT[i].lchild = HT[i].rchild = HT[i].parent = 0;//双亲,左右子树全部赋值为0
    }
    
    /*整个树的节点数是2*length-1,刨去第0个,就是2*length
    上面一个循环已经把叶子的权值存放
    剩下的节点就是树里面非叶子节点,里面不存放权值,
    初始化的时候,这里先把左右、双亲变量赋值为0*/
    for(;i < 2*length;i++)            /* i初值 = length+1;  */
    {
        HT[i].lchild = HT[i].rchild = HT[i].parent = 0;
    }

    for(i = length+1;i < 2*length;i++)
    {
        SelectHTNode(HT,i,&min1,&min2);
        HT[min1].parent = i;
        HT[min2].parent = i;
        HT[i].lchild = min1;
        HT[i].rchild = min2;
        HT[i].weight = HT[min1].weight + HT[min2].weight;
    }
}
/*==========================================================================*/
void SelectHTNode(HuffmanTree HT,int n,int *min1,int *min2) /* 查找最小和次小序号;  */
{
    int i;
    *min1 = *min2 = 0;
    for(i = 1;i < n;i++)
    {
        if(HT[i].parent == 0)
        {
           /* printf("\n i=%d,*min1=%d, HT[*min1].weight=%d",i,*min1,HT[*min1].weight);
            printf("\n i=%d,*min2=%d, HT[*min2].weight=%d",i,*min2,HT[*min2].weight);  */
            if(HT[*min1].weight >= HT[i].weight)
            {
                *min2 = *min1;
                *min1 = i;
              /*printf("\n i=%d: *min1=%d, *min2=%d ",i,*min1,*min2); */

            }
            else
                if(HT[*min2].weight > HT[i].weight)
                 {
                   *min2 = i;
                 /* printf("\n i=%d: *min1=%d, *min2=%d ",i,*min1,*min2);  */
                  }
        }
    }
}

/* 生成Huffman编码===============================================================  */
void HuffmanCoding1(HuffmanTree HT,int n,HuffmanCode HC)
{
  int i,start,c,f;
  char *cd;
  cd=(char * )malloc(n*sizeof(char)); /* 分配求编码的工作空间 */
  cd[n-1]='\0';
  for(i=1;i<=n;i++)                      /* 逐个字符求Huffman编码,注意i从1开始 */
  {
    start=n-1;                           /* 编码结束符位置 */
    for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent )  /* 从叶子到根逆向求编码 */
    {
      if (HT[f].lchild ==c)
          cd[--start]='0';
      else
          cd[--start]='1';
     }
     HC[i].code =(char*) malloc((n-start)*sizeof(char));  /* 为第i个字符编码分配空间 */
     strcpy(HC[i].code,&cd[start]);   /* 从cd 复制到HC[i].code */

  }
  free(cd);

}
/* ================================================================================  */

猜你喜欢

转载自blog.csdn.net/Xenoverse/article/details/83415597