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

如何释放树占用的内存,C?,c,tree,free,C,Tree,Free,我目前正在处理一个具有以下结构的通用树: 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 le

我目前正在处理一个具有以下结构的通用树:

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;
而分配不同节点的函数是(不要太在意键的值,基本上是分配子节点。如果没有,新的子节点将转到leftchild,否则将转到列表“node->leftchild->rightbrothers”的末尾):

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

 void DeleteTree(NODE **T) {

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

    free(*T);

 }
}
但它似乎不起作用,它甚至没有释放一个内存节点。 有没有关于我错在哪里或如何实施的想法? 另外,我从老师的伪代码中得到了递归函数的概念。然而,我不确定我是否用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

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

如果您对初始
malloc
比较幸运(或非常聪明),或者可以信任
realloc
在收缩块时不会移动块,那么这也可以减少分配的RAM量

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);
}
首先,阿美·塔沃里的情况是正确的,只要tmp!=无效的 基本上它不会工作,因为在DeleteTree(&tmp)之后,我无法再访问tmp中的内存,因为它显然已被删除,所以在for ends的第一个循环之后,我无法执行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中的问题,但是通过消除循环

因为我们递归地释放节点,所以我们也可以递归地完成整个过程

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