我在课堂上有一个任务,从霍夫曼树中返回一个被击中的符号数组。 函数getSL得到一个霍夫曼树(仅)并返回符号的敲击。 数组中的每个点都包含来自树的“叶子”的字符和 他的代码长度(到叶子的横截面数)。 我的主要问题是找到我如何推进arry的cnt,它不会直截了当。 谢谢。
typedef struct HNode {
char chr;
struct HNode *left, *right;
} HNode;
typedef struct {
char chr;
int counter;
}Symbol;
这就是我现在所做的。
Symbol * getSL(HNode *root) {
if (root->left == NULL && root->right == NULL) {
Symbol* b = (Symbol*)malloc(100);
b->counter=0;
b->chr = root->chr;
return b;
}
Symbol* a = (Symbol*)malloc(100);
if (root->left != NULL) {
a= getSL(root->left);
a->counter++;
}
if (root->right != NULL) {
a= getSL(root->right);
a->counter++;
}
return a;
}
答案 0 :(得分:0)
除了malloc问题(参见评论),你有一个基本的问题:你分配一个新的结构,然后将替换它与递归调用返回的结构。所以你失去了之前创建的那个(实际上,内存泄漏!)。
最简单的变体现在将您的符号转换为链接列表节点;然后你就可以做到:
Symbol* lastLeafFound; // probaly a function parameter!
if(!(root->left || root->right))
{
// leaf found:
Symbol* a = (Symbol*)malloc(sizeof(Symbol));
a->chr = root->chr;
a->counter = /* ... */;
a->next = NULL;
lastLeafFound->next = a;
// you might return a now as last leaf found, using it in the next recursive call
}
当然,上面的代码不完整,但应该给你一个想法......
如果你不能修改你的结构,那么你需要创建一个数组并将其传递给每个新的递归调用(而不是使用全局变量):
void doGetSL
(
HNode* root,
Symbol** symbols, // your array to be used
unsigned int* count, // number of symbols contained so far
unsigned int* capacity // maximum possible symbols
)
将所有数据作为指针传递允许函数根据需要修改它们,它们仍可从外部获取...
Symbol* getSL(HNode* root)
{
if(!root)
return NULL;
unsigned int count = 0;
unsigned int capacity = 128;
// allocate a whole array:
Symbol* array = malloc(capacity*sizeof(Symbol));
if(array) // malloc could fail...
{
doGetSL(root, &array, &count, &capacity);
// as you cannot return the number of leaves together with
// the array itself, you will need a sentinel:
array[count].chr = 0;
// obvious enough, I'd say, alternatively you could
// set counter to 0 or -1 (or set both chr and counter)
}
return array;
}
doGetSL
现在将使用上面设置的“基础设施”:
{
if(!(root->left || root->right))
{
if(*count == *capacity)
{
// no memory left -> we need a larger array!
// store in separate variables:
unsigned int c = *capacity * 2;
Symbol* s = realloc(symbols, c * sizeof(Symbol));
// now we can check, if reallocation was successful
// (on failure, s will be NULL!!!):
if(s)
{
// OK, we can use them...
*symbols = s; // <- need a pointer for (pointer to pointer)!
*capacity = c;
}
else
{
// re-allocation failed!
// -> need appropriate error handling!
}
}
(*symbols)[count].chr = root->chr;
(*symbols)[count].counter = /*...*/;
++*count;
}
else
{
if(root->left)
{
doGetSL(root->left, symbols, count, capacity);
}
if(root->right)
{
doGetSL(root->right, symbols, count, capacity);
}
}
}
有一点遗漏:设置计数器。这将非常简单:向doGetSL
添加另一个参数,指示当前深度,当您输入doGetSL时,您可以向右递增,然后您可以在需要时分配此值。
如果引入新结构,可以进一步改进上述变体(特别是可读性):
struct SLData
{
Symbol* symbols, // your array to be used
unsigned int count, // number of symbols contained so far
unsigned int capacity // maximum possible symbols
};
并传递这一个而不是三个指针:
doGetSL(HNode*, struct SLData*, unsigned int depth);
struct SLData data =
{
.count = 0;
.capacity = 128;
.array = malloc(capacity*sizeof(Symbol));
};
if(data.array)
doGetSL(root, &data, 0); // again passed as pointer!