[置顶] Huffman代码实现


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

typedef unsigned int u32;
typedef int status;

#define OK    1
#define ERROR 0
#define N 4
#define UINT_MAX 65535

/* huffman 算法用数组来表示树,设置父节点目的是用于从叶子节点到根编码 */
struct htnode
{
    u32 weight;
#if 0 
    struct htnode *lchild;
    struct htnode *rchild;  
    sturct htnode *father;
#endif
    int lchild;
    int rchild;
    int father; 
};

void select(struct htnode *HT , int n, int *s1, int *s2) 
{
    int i;
    u32 weight = UINT_MAX;
    
    for (i = 1; i <= n; i++)
    {
        if ((HT[i].father == 0) && (HT[i].weight < weight))
        {
            weight = HT[i].weight;
            (*s1) = i;
        }
    }

    weight = UINT_MAX;

    for (i = 1; i <= n; i++)
    {
        if (i == (*s1))
        {
            continue;
        }

        if ((HT[i].father == 0) && (HT[i].weight < weight))
        {
            weight = HT[i].weight;
            (*s2) = i;
        }

    }
}

/* 申请n+1个空间,实际上只用了n个。第0个不用是为了保持阅读代码清晰简便 */
status huffman_code(struct htnode **HT, char ***hc, int *w, int n)
{
    int i;
    int m;
    int s1,s2;
    int c,f;
    char *cd;
    int start;
    
    m = 2 * n - 1;

    (*HT) = (struct htnode*)malloc(sizeof(struct htnode) * (m + 1));
    if (!(*HT))
    {
        printf("%s: malloc failed\n", __FUNCTION__);
        return ERROR;
    }

    for (i = 1; i <= n; i++)
    {
       (*HT)[i].weight = w[i]; 
       (*HT)[i].lchild = 0;
       (*HT)[i].rchild = 0;
       (*HT)[i].father = 0;
    }

    for (i = n + 1; i <= m; i++)
    {
       (*HT)[i].weight = 0; 
       (*HT)[i].lchild = 0;
       (*HT)[i].rchild = 0;
       (*HT)[i].father = 0;
    }

    for (i = n + 1; i <= m; i++)
    {
       select(*HT, i - 1 , &s1, &s2); 
       printf("s1 = %d, s2 = %d\n", s1, s2);

       (*HT)[s1].father = i;
       (*HT)[s2].father = i;

       /* 此处不要写成w[s1] + w[s2]了 */
       (*HT)[i].weight = (*HT)[s1].weight + (*HT)[s2].weight;  
       (*HT)[i].lchild = s1;
       (*HT)[i].rchild = s2;
    }

    *hc = (char**) malloc(sizeof(char *) * (n + 1));
    if (!(*hc))
    {
        printf("%s: malloc failed\n", __FUNCTION__);
        return ERROR;
    }

    /* n个节点的编码长度最多为n-1,但留一个给'\0'作字符串结束 */
    cd = (char*)malloc(sizeof(char) * (n - 1 + 1));
    cd[n-1] = '\0';

    for (i = 1; i <= n; i++)
    {
        start = n-1;

        for (c = i,f = (*HT)[c].father; f != 0; c = f,f = (*HT)[c].father) 
        {
           if ((*HT)[f].lchild == c) 
           {
               cd[--start] = '0';
           }
           else
           {
               cd[--start] = '1';
           }
        }
        /* 多留一个字节给'\0'使用 */
        (*hc)[i] = (char *)malloc(sizeof(char) * (n - 1 - start + 1)); 
        if (!(*hc)[i])
        {
            printf("%s: malloc failed\n", __FUNCTION__);
            return ERROR;
        }

        strcpy((*hc)[i], &cd[start]);
    }
}

void print_code(char **HC, int *w, int n)
{
    int i;

    for (i = 1; i <= n; i++)
    {
        printf("the %d char(weight(%d))'s code is %s\n", i, w[i], HC[i]);  
    }
}

int main(void)
{
    struct htnode *HT;
    char **HC;
    int n = N;
    int w[N+1] = {-1, 3, 5, 2, 7};

    huffman_code(&HT, &HC, w, n); 
    print_code(HC, w, n);
}

你可能感兴趣的:([置顶] Huffman代码实现)