2015-07-22 46 views
0

我已經做了一些環顧四周,不能真正找到一個甚至解決這個想法的好資源。我們如何處理malloc在遞歸構建中失敗時釋放BST?

第一:衆所周知,我們應該總是檢查malloc()和realloc()是否返回null。

Word* temp; 
if ((temp = (Word*)malloc(sizeof(Word))) == NULL) { 
    fprintf(stderr, "unable to malloc for node.\n"); 
    exit(EXIT_FAILURE); 
} 

然而,我們也通常以遞歸的方式建立二叉搜索樹,像這樣:這在某種程度上類似於通常做

void buildTree(Word** tree, const char* input) { 
    //See if we have found the spot to insert the node. 
    //Do this by checking for NULL 
    if (!(*tree)) { 
     *tree = createNode(input); 
     return; 
    } 
    //else, move left or right accordingly. 
    if (strcmp(input, (*tree)->data) < 0) 
     buildTree(&(*tree)->left, input); 
    else 
     buildTree(&(*tree)->right, input); 
    return; 
} 

所以,我們做什麼,如果我們開始使用海量數據集和malloc()無法在遞歸buildTree函數中分配內存?我已經嘗試了很多東西來跟蹤「全局錯誤」標誌和「全局頭」節點指針,它似乎越來越雜亂,越多我嘗試。使用構建BST的例子似乎很少考慮malloc()失敗,所以它們在這方面並沒有真正的幫助。

我可以合乎邏輯地看到一個答案是「不要每次都使用遞歸併返回樹的頭部」。雖然我明白了爲什麼會這樣,但我是一名本科TA,我們使用BST教授的內容之一是遞歸。因此,當我們正在教授遞歸時,對學生說「不要使用遞歸」會是自欺欺人的。

任何想法,建議或鏈接將不勝感激。

+1

爲什麼當你的'buildTree'函數可以有一個完美的返回類型時,你需要一個全局錯誤標誌? (也就是說,爲什麼不只是讓'buildTree'返回一個錯誤代碼,然後在失敗時傳播它呢?) – jamesdlin

+0

你沒有錯,但是這並沒有真正解決這個問題......除非我誤解你?即使我做了「c樣式」的錯誤處理返回一個int來表示成功或失敗,我仍然不知道如何處理釋放malloc()失敗之前分配的節點... Can如果我似乎誤解了你的建議,你可能會擴展你的想法?我將如何檢查函數內的遞歸調用的結果?你能提供一個例子嗎?我認爲你可能會做些什麼,但我不確定... – TylerN

+1

你可以一直傳播錯誤代碼,並讓調用者負責釋放樹,如果它只是部分構建。你可以通過引入一個包裝函數來執行初始的'buildTree'調用來使它更好一些,然後這個函數將負責清理失敗。 – jamesdlin

回答

1

我們通常使用返回錯誤並讓調用者釋放它,畢竟它可以很好地釋放其他非關鍵資源並嘗試再次插入節點。

#define BUILD_OK  0 
#define BUILD_FAILED 1 

int buildTree(Word** tree, const char* input) { 
    int res; 

    //See if we have found the spot to insert the node. 
    //Do this by checking for NULL 
    if (!(*tree)) { 
     if (!(*tree = createNode(input))) 
      return BUILD_FAILED; 

     //Maybe other checks 

     return BUILD_OK; 
    } 
    //else, move left or right accordingly. 
    if (strcmp(input, (*tree)->data) < 0) 
     res = buildTree(&(*tree)->left, input); 
    else 
     res = buildTree(&(*tree)->right, input); 

    return res; 
} 
+0

OH! -_-,好吧,我沒有考慮自由自下而上的節點。我正在努力保持對樹頭的建造時的參考。其中,第一次通話後依然不會改變......呵呵。好吧,謝謝! – TylerN

+2

由於遞歸路徑不訪問樹中的所有節點,建議的「自下而上」自由序列將不起作用。所以沒有釋放,而是讓函數的原始調用者處理錯誤 – user3629249

+0

@ user3629249好抓!我完全錯過了! – 2015-07-23 15:11:53