如何释放树,C占用的内存?

How to free memory occupied by a Tree, C?

我目前正在处理具有这种结构的通用树:

typedef struct NODE {

    //node's keys
    unsigned short *transboard;
    int depth;
    unsigned int i; 
    unsigned int j;
    int player;
    int value;


    struct NODE *leftchild; //points to the first child from the left
    struct NODE *rightbrothers; //linked list of brothers from the current node

}NODE;

static NODE *GameTree = NULL;

虽然分配不同节点的函数是(不要太在意键的值,基本上分配 children-nodes。如果没有新的 child向左 child,否则它会在列表末尾 "node->leftchild->rightbrothers"):

static int AllocateChildren(NODE **T, int depth, unsigned int i, unsigned int j, int player, unsigned short *transboard) {
NODE *tmp = NULL;

if ((*T)->leftchild == NULL) {
    if(  (tmp = (NODE*)malloc(sizeof(NODE))  )== NULL) return 0;
    else {
        tmp->i = i;
        tmp->j = j;
        tmp->depth = depth;
        (player == MAX ) ? (tmp->value = 2 ): (tmp->value = -2);
        tmp->player = player;
        tmp->transboard = transboard;

        tmp->leftchild = NULL;
        tmp->rightbrothers = NULL;

        (*T)->leftchild = tmp;
    }
}

else {
    NODE *scorri = (*T)->leftchild;
    while (scorri->rightbrothers != NULL)
        scorri = scorri->rightbrothers;

    if( ( tmp = (NODE*)malloc(sizeof(NODE)) )== NULL) return 0;
    else {
        tmp->i = i;
        tmp->j = j;
        tmp->depth = depth;
        (player == MAX) ? (tmp->value = 2) : (tmp->value = -2);
        tmp->player = player;
        tmp->transboard = transboard;

        tmp->leftchild = NULL;
        tmp->rightbrothers = NULL;
    }
    scorri->rightbrothers = tmp;


}

return 1;

}

我需要想出一个函数,可能是递归的,它会释放整个树,到目前为止我已经想出这个:

 void DeleteTree(NODE **T) {

 if((*T) != NULL) {
    NODE *tmp;
    for(tmp = (*T)->children; tmp->brother != NULL; tmp = tmp->brother) {
        DeleteTree(&tmp);
    }

    free(*T);

 }
}

但它似乎不起作用,它甚至没有释放单个内存节点。 关于我错在哪里或如何实施的任何想法? P.s。我从我老师的伪代码中得到了递归函数的概念。但是我不确定我是否用我的树在 C 语言中正确翻译了它。 伪代码:

1: function DeleteTree(T)
2:    if T != NULL then
3:       for c ∈ Children(T) do
4:          DeleteTree(c)
5:       end for
6:       Delete(T)
7:    end if
8: end function

如果我要分配大量将同时消失的树节点,我喜欢做的一件事是在 'batches' 中分配它们。我 malloc 然后作为节点数组,并在保存指向数组的指针(在如下函数中)后从特殊的 nodealloc 函数中分发它们。要删除树,我只是确保我没有保留任何引用,然后调用免费例程(也如下所示)。

这也可以减少您分配的 RAM 量,如果您很幸运(或非常聪明)您的初始 malloc 或者可以相信 realloc 在您缩小块时不会移动它.

struct freecell { struct freecell * next; void * memp; } * saved_pointers = 0;

static void
save_ptr_for_free(void * memp)
{
    struct freecell * n = malloc(sizeof*n);
    if (!n) {perror("malloc"); return; }
    n->next = saved_pointers;
    n->memp = memp;
    saved_pointers = n;
}

static void
free_saved_memory(void)
{
    while(saved_pointers) {
        struct freecell * n = saved_pointers;
        saved_pointers = saved_pointers->next;
        free(n->memp);
        free(n);
    }
}

我刚刚意识到我在代码中犯了一个大错误,我会自己回答,因为没有人找到答案。

错误出在这段代码:

for(tmp = (*T)->children; tmp->brother != NULL; tmp = tmp->brother) {
    DeleteTree(&tmp);
}

首先,Ami Tavory 对 for 条件的看法是正确的,只要 tmp != NULL,我就需要继续 基本上它不会工作,因为在 DeleteTree(&tmp) 之后,我无法再访问 tmp 中的内存,因为 它显然被删除了 ,所以在 for 结束的第一个循环之后我可以' t do tmp = tmp->rightbrother 移动到下一个要删除的节点,因为 tmp->rightbrother 不再存在,因为我刚刚删除了它。 为了修复它,我只需要将 tmp->brother 保存在其他地方:

void DeleteTree(NODE **T) {

   if((*T) != NULL) {
       NODE *tmp, *deletenode, *nextbrother;

       for(tmp = (*T)->children; tmp != NULL; tmp = nextbrother) {
           nextbrother = tmp->rightbrother;
           DeleteTree(&tmp);

       }

   canc = (*T);
   free(*T);
   (*T) = NULL;
  }

}

为了完整起见,我想添加我的 DeleteTree 版本

void DeleteTree(NODE *T) {
  if(T != NULL) {
    DeleteTree(T->rightbrothers);
    DeleteTree(T->leftchild);
    free(T);
  }
}

我认为它不那么晦涩,也更容易阅读。它基本上解决了 DeleteTree 中的问题,但通过消除循环。

由于我们递归地释放节点,所以我们不妨递归地完成整个过程。