Huffman编码

#define MAX_WEIGHT 255

typedef struct 
{
    int weight;
    int traverseMark;
    int parent, lchild, rchild;
}HTNode, *HuffmanTree;
typedef char ** HuffmanCode;
HuffmanTree HT = nil;
HuffmanCode HC = nil;
int *markSelect = nil;
int min1 = 0;
int min2 = 0;
void HTselect(int length)
{
    int min = MAX_WEIGHT;
    for (int i = 0; i < length; i++)
    {
        if ((HT[i].weight < min)&&(markSelect[i] == 0))
        {
            min = HT[i].weight;
            min1 = i;
        }
    }
    
    markSelect[min1] = 1;

    min = MAX_WEIGHT;
    for (int i = 0; i < length; i++)
    {
        if ((HT[i].weight < min)&&(markSelect[i] == 0))
        {
            min = HT[i].weight;
            min2 = i;
        }
    }
    markSelect[min2] = 1;

    return;
}
void HuffmanCoding(int *w, int n)
{
    if (n <= 1)
    {
        return;
    }
    int m = 2*n - 1;
    HT = (HuffmanTree)malloc(m * sizeof(HTNode));
    
    //used in HTSelect for marking the traversed node;
    markSelect = (int *)malloc(m * sizeof(int));
    for (int q = 0; q < m; q++)
    {
        markSelect[q] = 0;
    }
    
    //init the node weight and status
    HuffmanTree p = HT;
    int i = 0;
    for (;i < n; ++i, ++p)
    {
        p->weight = w[i];
        p->parent = MAX_WEIGHT;
        p->lchild = MAX_WEIGHT;
        p->rchild = MAX_WEIGHT;
        p->traverseMark = 0;
    }
    for (; i < m; ++i, ++p)
    {
        p->weight = 0;
        p->parent = MAX_WEIGHT;
        p->lchild = MAX_WEIGHT;
        p->rchild = MAX_WEIGHT;
        p->traverseMark = 0;
    }
    
    //constuct the Huffman tree
    //1...n is leaf nodes
    //n+1....m is not leaf nodes
    for (int j = n; j < m; j++)
    {
        HTselect(j);
        //
        HT[min1].parent = j;
        HT[min2].parent = j;
        HT[j].lchild = min1;
        HT[j].rchild = min2;
        HT[j].weight = HT[min1].weight + HT[min2].weight;
    }
    //print the Huffman tree
    p = HT;
    for (int j = 0; j < m; p++, j++)
    {
        NSLog(@"%d, %d, %d, %d", p->weight, p->parent, p->lchild, p->rchild);
    }
}


//get the Huffman code from the Huffman root to the leaf
void HuffmanGetCode(int n)
{
    int p = 2*n - 1 - 1;
    HC = (HuffmanCode)malloc(n * sizeof(char *));
    char *cd = (char *)malloc(n * sizeof(char));
    int cdlen = 0;
    while (p != MAX_WEIGHT)
    {
        if (HT[p].traverseMark == 0)
        {
            HT[p].traverseMark = 1;
            if (HT[p].lchild != MAX_WEIGHT)
            {
                p = HT[p].lchild;
                cd[cdlen++] = '0';
            }
            else {
                HC[p] = (char *)malloc((cdlen + 1) *sizeof(char));
                cd[cdlen] = '\0';
                strcpy(HC[p], cd);
            }
            
        }
        else if (HT[p].traverseMark == 1)
        {
            HT[p].traverseMark = 2;
            if (HT[p].rchild != MAX_WEIGHT)
            {
                p = HT[p].rchild;
                cd[cdlen++] = '1';
            }
        }
        else
        {
            cdlen--;
            HT[p].traverseMark = 0;
            p = HT[p].parent;

        }
    }
    for (int i = 0; i < n; i++)
    {
        printf("%s\n", HC[i]);
    }
}

//decode the information using the Huffman tree
void HTDecode(int *code, int elementCount, int n)
{
    int i = 0;
    int j = 0;
    int p = 2*elementCount - 1 - 1;
    int decode[MAX_WEIGHT]; 

    while (i < n)
    {
        if (code[i] == 0)
        {
            if (HT[p].lchild != MAX_WEIGHT)
            {
                i++;
                p = HT[p].lchild;
            }
            else
            {
                decode[j++] = p;
                p = 2*elementCount - 1 - 1;
            }
        }
        else
        {
            if (HT[p].rchild != MAX_WEIGHT)
            {
                i++;
                p = HT[p].rchild;
            }
            else
            {
                decode[j++] = p;
                p = 2*elementCount - 1 - 1;
            }
        }
    }
    decode[j] = p;
    for(int i = 0; i <= j; i++)
    {
        printf("%d", decode[i]);
    }
    
}

-(void)main
{
    int weight[5] = {4,5,8,9,12};
    HuffmanCoding(weight, 5);
    HuffmanGetCode(5);
    int code[12] = {0,0,1,0,0,0,1,1,1,1,0,1};
    HTDecode(code, 5, 12);
}


a.cpp:55:3: error: conflicting declaration ‘typedef struct HTNode HTNode’ 55 | } HTNode, *HuffmanTree; | ^~~~~~ a.cpp:10:3: note: previous declaration as ‘typedef struct HTNode HTNode’ 10 | } HTNode, *HuffmanTree; | ^~~~~~ a.cpp:55:12: error: conflicting declaration ‘typedef struct HTNode* HuffmanTree’ 55 | } HTNode, *HuffmanTree; | ^~~~~~~~~~~ a.cpp:10:12: note: previous declaration as ‘typedef struct HTNode* HuffmanTree’ 10 | } HTNode, *HuffmanTree; | ^~~~~~~~~~~ a.cpp:128:5: error: redefinition of ‘int main()’ 128 | int main() { | ^~~~ a.cpp:16:5: note: ‘int main()’ previously defined here 16 | int main() { | ^~~~ a.cpp: In function ‘int main()’: a.cpp:21:14: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 21 | scanf("%d", &n); | ~~~~~^~~~~~~~~~ a.cpp:25:22: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 25 | scanf("%d", &w[i]); | ~~~~~^~~~~~~~~~~~~ a.cpp: In function ‘int main()’: a.cpp:130:10: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 130 | scanf("%d", &n); | ~~~~~^~~~~~~~~~ a.cpp:133:14: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 133 | scanf("%d", &w[i]); | ~~~~~^~~~~~~~~~~~~a.cpp:55:3: error: conflicting declaration ‘typedef struct HTNode HTNode’ 55 | } HTNode, *HuffmanTree; | ^~~~~~ a.cpp:10:3: note: previous declaration as ‘typedef struct HTNode HTNode’ 10 | } HTNode, *HuffmanTree; | ^~~~~~ a.cpp:55:12: error: conflicting declaration ‘typedef struct HTNode* HuffmanTree’ 55 | } HTNode, *HuffmanTree; | ^~~~~~~~~~~ a.cpp:10:12: note: previous declaration as ‘typedef struct HTNode* HuffmanTree’ 10 | } HTNode, *HuffmanTree; | ^~~~~~~~~~~ a.cpp:128:5: error: redefinition of ‘int main()’ 128 | int main() { | ^~~~ a.cpp:16:5: note: ‘int main()’ previously defined here 16 | int main() { | ^~~~ a.cpp: In function ‘int main()’: a.cpp:21:14: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 21 | scanf("%d", &n); | ~~~~~^~~~~~~~~~ a.cpp:25:22: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 25 | scanf("%d", &w[i]); | ~~~~~^~~~~~~~~~~~~ a.cpp: In function ‘int main()’: a.cpp:130:10: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 130 | scanf("%d", &n); | ~~~~~^~~~~~~~~~ a.cpp:133:14: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 133 | scanf("%d", &w[i]); | ~~~~~^~~~~~~~~~~~~
最新发布
11-21
### 解决 typedef 重复声明问题 在C语言中,typedef 用于为已有的类型创建一个新的名字。若出现 typedef 重复声明,可能是在不同地方对同一类型进行了重复定义。例如 `typedef struct HTNode HTNode` 和 `typedef struct HTNode* HuffmanTree`,若重复声明,可将其放在一个统一的头文件中,且只声明一次。 示例代码如下: ```c // 假设将其放在 huffman.h 头文件中 #ifndef HUFFMAN_H #define HUFFMAN_H typedef struct { int weight; int parent; int lchild; int rchild; } HTNode, *HuffmanTree; typedef char ** HuffmanCode; #endif ``` 在使用这些类型的源文件中包含该头文件: ```c #include "huffman.h" ``` ### 解决 main 函数重定义问题 main 函数是C程序的入口点,一个程序中只能有一个 main 函数。若出现 main 函数重定义,需检查代码中是否存在多个 main 函数定义。若有,保留一个 main 函数,删除其他的。 ### 解决 scanf 函数返回值被忽略警告问题 scanf 函数返回成功匹配并赋值的输入项数量。忽略其返回值可能会导致输入错误未被检测到。可通过检查 scanf 的返回值来解决该警告。 示例代码如下: ```c int n; if (scanf("%d", &n) != 1) { // 处理输入错误 fprintf(stderr, "输入错误,请输入一个整数。\n"); return 1; } ``` ### 完整示例代码 ```c // huffman.h #ifndef HUFFMAN_H #define HUFFMAN_H typedef struct { int weight; int parent; int lchild; int rchild; } HTNode, *HuffmanTree; typedef char ** HuffmanCode; void SelectTwoMin(int upbound, HuffmanTree HT, int *s1, int *s2); void HuffmanCoding(HuffmanTree *HT, HuffmanCode *HC, int *w, int n); #endif // huffman.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include "huffman.h" void SelectTwoMin(int upbound, HuffmanTree HT, int *s1, int *s2) { int min1 = 1000, min2 = 1000; *s1 = 0; *s2 = 0; for (int i = 1; i <= upbound; i++) { if (HT[i].parent == 0) { if (HT[i].weight < min1) { min2 = min1; *s2 = *s1; min1 = HT[i].weight; *s1 = i; } else if (HT[i].weight < min2) { min2 = HT[i].weight; *s2 = i; } } } } void HuffmanCoding(HuffmanTree *HT, HuffmanCode *HC, int *w, int n) { int m = 2 * n - 1; *HT = (HuffmanTree)malloc((m + 1) * sizeof(HTNode)); for (int i = 1; i <= n; i++) { (*HT)[i].weight = w[i - 1]; (*HT)[i].parent = 0; (*HT)[i].lchild = 0; (*HT)[i].rchild = 0; } for (int i = n + 1; i <= m; i++) { (*HT)[i].weight = 0; (*HT)[i].parent = 0; (*HT)[i].lchild = 0; (*HT)[i].rchild = 0; } for (int i = n + 1; i <= m; i++) { int s1, s2; SelectTwoMin(i - 1, *HT, &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; } *HC = (HuffmanCode)malloc((n + 1) * sizeof(char *)); char *cd = (char *)malloc(n * sizeof(char)); cd[n - 1] = '\0'; for (int i = 1; i <= n; i++) { int 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((n - start) * sizeof(char)); strcpy((*HC)[i], &cd[start]); } free(cd); } // main.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include "huffman.h" int main() { HuffmanTree ht; HuffmanCode hc; int n; if (scanf("%d", &n) != 1) { fprintf(stderr, "输入错误,请输入一个整数。\n"); return 1; } int *w = (int *)malloc(n * sizeof(int)); for (int i = 0; i < n; i++) { if (scanf("%d", &w[i]) != 1) { fprintf(stderr, "输入错误,请输入整数。\n"); free(w); return 1; } } HuffmanCoding(&ht, &hc, w, n); for (int i = 1; i <= 2 * n - 1; i++) { printf("%d %d %d %d\n", ht[i].weight, ht[i].parent, ht[i].lchild, ht[i].rchild); } for (int i = 1; i <= n; i++) printf("%s\n", hc[i]); free(w); free(ht); for (int i = 1; i <= n; i++) free(hc[i]); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值