如何释放树占用的内存,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);
}
}