递归结构和 malloc()

发布于 2024-12-18 15:04:08 字数 1016 浏览 5 评论 0原文

我有一个递归struct,它是:

typedef struct dict dict;
struct dict {
    dict *children[M];
    list *words[M];
};

这样初始化:

dict *d = malloc(sizeof(dict));
bzero(d, sizeof(dict));

我想知道bzero()在这里到底做了什么,以及我如何malloc()< /code> 对于孩子来说是递归的。

编辑:这就是我希望能够 malloc() childrenwords 的方式:

void dict_insert(dict *d, char *signature, unsigned int current_letter, char *w) {
    int occur;
    occur = (int) signature[current_letter];
    if (current_letter == LAST_LETTER) {
        printf("word found : %s!\n",w);
        list_print(d->words[occur]);
        char *new;
        new = malloc(strlen(w) + 1);
        strcpy(new, w);
        list_append(d->words[occur],new);
        list_print(d->words[occur]);
    }
    else {
        d = d->children[occur];
        dict_insert(d,signature,current_letter+1,w);
    }
}

I have a recursive struct which is:

typedef struct dict dict;
struct dict {
    dict *children[M];
    list *words[M];
};

Initialized this way:

dict *d = malloc(sizeof(dict));
bzero(d, sizeof(dict));

I would like to know what bzero() exactly does here, and how can I malloc() recursively for children.

Edit: This is how I would like to be able to malloc() the children and words:

void dict_insert(dict *d, char *signature, unsigned int current_letter, char *w) {
    int occur;
    occur = (int) signature[current_letter];
    if (current_letter == LAST_LETTER) {
        printf("word found : %s!\n",w);
        list_print(d->words[occur]);
        char *new;
        new = malloc(strlen(w) + 1);
        strcpy(new, w);
        list_append(d->words[occur],new);
        list_print(d->words[occur]);
    }
    else {
        d = d->children[occur];
        dict_insert(d,signature,current_letter+1,w);
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

青春有你 2024-12-25 15:04:08

bzero(3) 将内存初始化为零。相当于使用第二个参数调用 memset(3)为 0。在这种情况下,它将所有成员变量初始化为空指针。 bzero 已被视为已弃用,因此您应该将其替换为 memset;或者,您可以只调用 calloc(3) 而不是malloc,成功后会自动将返回的内存清零。

您不应该使用您编写的两个强制转换中的任何一个 - 在 C 中,void* 指针可以隐式强制转换为任何其他指针类型,并且任何指针类型都可以隐式强制转换为 void *。 malloc 返回一个 void*,因此您可以将其分配给您的 dict *d 变量,而无需进行强制转换。同样,bzero 的第一个参数是 void*,因此您可以直接将您的 d 变量传递给它,而无需进行强制转换。

要理解递归,首先要理解递归。如果您想避免无限分配内存,请确保您有适当的基本情况。

bzero(3) initializes the memory to zero. It's equivalent to calling memset(3) with a second parameter of 0. In this case, it initializes all of the member variables to null pointers. bzero is considered deprecated, so you should replace uses of it with memset; alternatively, you can just call calloc(3) instead of malloc, which automatically zeroes out the returned memory for you upon success.

You should not use either of the two casts you have written—in C, a void* pointer can be implicitly cast to any other pointer type, and any pointer type can be implicitly cast to void*. malloc returns a void*, so you can just assign it to your dict *d variable without a cast. Similarly, the first parameter of bzero is a void*, so you can just pass it your d variable directly without a cast.

To understand recursion, you must first understand recursion. Make sure you have an appropriate base case if you want to avoid allocating memory infinitely.

沉鱼一梦 2024-12-25 15:04:08

一般来说,当您不确定编译器为您生成什么时,最好使用 printf 来报告结构的大小。在这种情况下,dict的大小应该是2 * M * 指针的大小。在这种情况下,bzero 将用零填充字典。换句话说,children 和 Words 数组的所有 M 个元素都将为零。

为了初始化该结构,我建议创建一个函数,该函数接受一个指向字典的指针并分配每个子项,然后调用自身来初始化它:

void init_dict(dict* d)
{
    int i;
    for (i = 0; i < M; i++)
    {
        d->children[i] = malloc(sizeof(dict));
        init_dict(d->children[i]);

        /* initialize the words elements, too */
    }
}

如果您能明白为什么此代码无法按原样工作,请+1。 (提示:它有一个无限递归错误,需要一个规则来告诉它子树需要多深才能停止递归。)

In general, when you are unsure what the compiler is generating for you, it is a good idea to use a printf to report the size of the struct. In this case, the size of dict should be 2 * M * the size of a pointer. In this case, bzero will fill a dict with zeros. In other words, all M elements of the children and words arrays will be zero.

To initialize the structure, I recommend creating a function that takes a pointer to a dict and mallocs each child and then calls itself to initialize it:

void init_dict(dict* d)
{
    int i;
    for (i = 0; i < M; i++)
    {
        d->children[i] = malloc(sizeof(dict));
        init_dict(d->children[i]);

        /* initialize the words elements, too */
    }
}

+1 to you if you can see why this code won't work as is. (Hint: it has an infinite recursion bug and needs a rule that tells it how deep the children tree needs to be so it can stop recursing.)

夜唯美灬不弃 2024-12-25 15:04:08

bzero 只是将内存归零。 bzero(addr, size) 本质上等同于 memset(addr, 0, size)。至于为什么要使用它,从我所看到的大约一半的使用时间来看,这只是因为有人认为将内存归零似乎是一个好主意,尽管它并没有真正完成任何事情。在这种情况下,看起来效果是将一些指针设置为 NULL(尽管为此目的它并不完全可移植)。

要递归分配,您基本上只需跟踪当前深度,并分配子节点,直到达到所需的深度。按此顺序编写一些代码就可以完成这项工作:

void alloc_tree(dict **root, size_t depth) { 
    int i;
    if (depth == 0) {
        (*root) = NULL;
        return;
    }

    (*root) = malloc(sizeof(**root));

    for (i=0; i<M; i++)
        alloc_tree((*root)->children+i, depth-1);       
}

我应该补充一点,我无法想象像这样进行递归分配。在典型情况下,您插入数据,并根据需要分配新节点来保存数据。具体细节将取决于您是否(以及如何)保持树平衡。对于像这样的多路树,使用某些 B 树变体是相当常见的,在这种情况下,我上面给出的代码通常根本不适用——使用 B 树,您可以填充一个节点,当它达到极限时,将其分成两半并将中间项提升到父节点。当新节点到达树的顶部并且根节点已满时,您将分配一个新节点。

bzero just zeros the memory. bzero(addr, size) is essentially equivalent to memset(addr, 0, size). As to why you'd use it, from what I've seen around half the time it's used, it's just because somebody though zeroing the memory seemed like a good idea, even though it didn't really accomplish anything. In this case, it looks like the effect would be to set some pointers to NULL (though it's not entirely portable for that purpose).

To allocate recursively, you'd basically just keep track of a current depth, and allocate child nodes until you reached the desired depth. Code something on this order would do the job:

void alloc_tree(dict **root, size_t depth) { 
    int i;
    if (depth == 0) {
        (*root) = NULL;
        return;
    }

    (*root) = malloc(sizeof(**root));

    for (i=0; i<M; i++)
        alloc_tree((*root)->children+i, depth-1);       
}

I should add that I can't quite imagine doing recursive allocation like this though. In a typical case, you insert data, and allocate new nodes as needed to hold the data. The exact details of that will vary depending on whether (and if so how) you're keeping the tree balanced. For a multi-way tree like this, it's fairly common to use some B-tree variant, in which case the code I've given above won't normally apply at all -- with a B-tree, you fill a node, and when it's reached its limit, you split it in half and promote the middle item to the parent node. You allocate a new node when this reaches the top of the tree, and the root node is already full.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文