我已經做了一些環顧四周,不能真正找到一個甚至解決這個想法的好資源。我們如何處理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教授的內容之一是遞歸。因此,當我們正在教授遞歸時,對學生說「不要使用遞歸」會是自欺欺人的。
任何想法,建議或鏈接將不勝感激。
爲什麼當你的'buildTree'函數可以有一個完美的返回類型時,你需要一個全局錯誤標誌? (也就是說,爲什麼不只是讓'buildTree'返回一個錯誤代碼,然後在失敗時傳播它呢?) – jamesdlin
你沒有錯,但是這並沒有真正解決這個問題......除非我誤解你?即使我做了「c樣式」的錯誤處理返回一個int來表示成功或失敗,我仍然不知道如何處理釋放malloc()失敗之前分配的節點... Can如果我似乎誤解了你的建議,你可能會擴展你的想法?我將如何檢查函數內的遞歸調用的結果?你能提供一個例子嗎?我認爲你可能會做些什麼,但我不確定... – TylerN
你可以一直傳播錯誤代碼,並讓調用者負責釋放樹,如果它只是部分構建。你可以通過引入一個包裝函數來執行初始的'buildTree'調用來使它更好一些,然後這個函數將負責清理失敗。 – jamesdlin