C:霍夫曼编码

时间:2015-02-27 20:07:27

标签: c huffman-code

我需要编写一个函数,它是系统的一部分,用于对字符串使用huffman编码。此特定函数扫描字符串,然后根据字符串中的字符生成单个霍夫曼树的列表。但是,当我运行它时,此功能不起作用。任何人都可以帮我弄清楚这个功能有什么问题吗?

hufflist* build_hufflist(char* s)
{
    char* letters = malloc(strlen(s));
    int x;

    int letterspos = 0;
    hufflist* output = malloc(sizeof(hufflist));
    output = NULL;

    char* scopy = strdup(s);
    make_capital(scopy);

    for(x = 0 ; x < strlen(s) ; x++) {
        if(('a' <= scopy[x]) && (scopy[x] <= 'z')) {
            scopy[x] -= 32;
        }

        if(char_in_array(letters, s[x] == 0)) {
            letters[letterspos] = scopy[x];
            letterspos++;
            hl_insert(output, huff_singleton(scopy[x], char_count(scopy, scopy[x])));
        }
    }
    return output;
}

char_in_array是一个函数,它返回一个字符是否在数组中,而char_count返回一个字符在数组中的次数。我已经对它们进行了测试,但它们都有效。

此外,这里还有相关的数据定义

typedef struct leaf leaf;
typedef struct node node;
typedef struct huff huff;
typedef struct hufflist hufflist;

enum huff_tag { LEAF, NODE };

struct leaf {
    char c;
    int n;
};

struct node {
    int n;
    huff *lsub;
    huff *rsub;
};

union huff_union {
    leaf leaf;
    node node;
};

struct huff {
    enum huff_tag tag;
    union huff_union h;
};

struct hufflist {
    huff* val;
    hufflist* next;
};

1 个答案:

答案 0 :(得分:2)

以下是我发现的一些问题。

1)你malloc letters,然后开始使用它而不初始化它指向任何基本情况的数据(例如 - 所有0,或s的副本,等等。)。相反,如果letterspos = 0表示letters为空,那么char_in_array()也可能需要该信息。

2)你是malloc output,但是立即将它设置为NULL并最终返回。

3)您在make_capital()上调用scopy,然后在循环中执行类似的逻辑。

4)为第二个参数传递一个布尔值(0或1)到char_in_array()。您可能打算在== 0之外拨打char_in_array()

4a)函数char_in_array()只接受指向letters的指针和要检查的字符。例如,它不会以letterspos为例。所以,&#34;结束&#34; letters必须嵌入数组本身(例如,使用nul-terminator参见1))或者你也需要传递letterspos

hufflist* build_hufflist(char* s)
{
    char* letters = malloc(strlen(s));  // 1) maybe calloc(strlen(s), 1) or calloc(256, 1) instead?
    int x;

    int letterspos = 0;
    hufflist* output = malloc(sizeof(hufflist));
    output = NULL;  // 2) probably not what you intended

    char* scopy = strdup(s);
    make_capital(scopy);

    for(x = 0 ; x < strlen(s) ; x++) {
        if(('a' <= scopy[x]) && (scopy[x] <= 'z')) {  // 3) didn't make_capital() already do this?
            scopy[x] -= 32;
        }

        if(char_in_array(letters, s[x] == 0)) {  // 4) should the == 0 be outside the call to char_in_arrays? 4a) doesn't char_in_array need letterspos too?
            letters[letterspos] = scopy[x];
            letterspos++;
            hl_insert(output, huff_singleton(scopy[x], char_count(scopy, scopy[x])));
        }
    }
    return output;
}

编辑看起来您的代码会重复扫描整个字符串(即 - 您为找到的每个新字符调用char_count()),这不是最佳选择。您可以在一次传递中获得字符串中所有字符的计数,如下所示:

unsigned int char_counts[256] = { 0 };
unsigned char *ptr = (unsigned char*) scopy;

for (; *ptr; ++ptr)
  ++char_counts[*ptr];

char_counts现在包含copy中包含的每个字符的计数,由(无符号)字符值本身索引。字符串中未包含的字符的计数为零。那么你可以这样做:

for (x = 0; x < 256; ++x)
  if (char_counts[x])
    hl_insert(output, huff_singleton(x, char_counts[x]));

我假设插入的顺序并不重要,这可能是也可能不是。