2015-05-17 66 views
-1

我目前正在處理一個普通的樹這種結構:如何釋放一棵樹佔用的內存,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; 

雖然是分配不同節點的功能(也懶得在鍵的值太多,基本上分配孩子節點如果沒有任何新的孩子去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); 

} 
} 

但它似乎不工作,它甚至不釋放內存的單個節點。 關於我在哪裏出錯或者如何實施的任何想法? 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 

回答

0

我剛剛意識到自己在代碼中犯了大錯,我只是回答自己,因爲沒有人找到答案。

錯誤就出在這一段代碼:

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

首先阿美Tavory的是對有關的條件,我需要只要繼續擔任TMP = NULL 基本上也不會只是因爲在刪除樹之後(& tmp),我不能再訪問tmp中的內存,因爲它明顯被刪除了,所以在第一個循環結束之後,我無法執行tmp = tmp-> rightbrother來移動下一個節點刪除,因爲tmp-> rightbrother不再存在,因爲我剛刪除它。 爲了解決這個問題我只需要保存TMP->哥別的地方:

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; 
    } 

} 
0

一件事,就是在「批次」進行分配。 I 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); 
    } 
} 
0

只是爲了完整起見我想補充DeleteTree我的版本

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

我認爲這不那麼模糊並且更容易閱讀。基本上它解決了DeleteTree中的問題,但通過消除循環。

由於我們以遞歸方式釋放節點,我們可能會遞歸地完成整個過程。