2015-07-22 49 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