【问题标题】:How to free memory occupied by a Tree, C?如何释放 Tree, C 占用的内存?
【发布时间】:2015-05-17 18:59:16
【问题描述】:

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

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,否则它去列表“节点->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);

 }
}

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

【问题讨论】:

    标签: c tree free


    【解决方案1】:

    如果我要分配大量将同时消失的树节点,我喜欢做的一件事是“批量”分配它们。我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);
        }
    }
    

    【讨论】:

      【解决方案2】:

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

      错误在于这段代码:

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

      首先,Ami Tavory 对 for 条件的看法是正确的,我需要继续,只要 tmp != NULL 基本上它不会起作用,因为在 DeleteTree(&tmp) 之后,我不能再访问 tmp 中的内存,因为 它显然被删除了,所以在第一个循环结束后我不能做 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;
        }
      
      }
      

      【讨论】:

        【解决方案3】:

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

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

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

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

        【讨论】:

          猜你喜欢
          • 2015-10-26
          • 2013-02-23
          • 1970-01-01
          • 1970-01-01
          • 2015-08-10
          • 2012-08-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多