我有这段代码从内存中删除二进制树,但是当你对destroy(<#node* tree#>)
进行递归调用时,我不知道堆栈的外观或递归的工作原理。我知道当你到达一个分支的末尾时递归就结束了,所以结束了那个调用并在递归中开始上升,但是如果一个递归函数调用保持在它停止的地方,那么对destroy(tree->right)
的调用是否等待在destroy(tree->left)
结束时被执行?
struct node{
int value;
node* left;
node* right;
};
void destroy(node* tree){
if(tree != NULL){
destroy(tree->left);
destroy(tree->right);
delete tree;
}
}
答案 0 :(得分:2)
destroy(tree-> left)在destroy(tree-&gt; right)之前完全执行。
但是,请记住左侧树有左侧和右侧。所以在这里它将再次首先向左前进,然后在返回的路上向右前进。右边可能包含左边的节点,这些节点首先被处理。
堆栈对此影响不大。每当你进入树的一个杠杆(即向左或向右调用destroy)时,函数调用可能会将一些变量推送到堆栈 - 例如返回地址和当前节点指针。当到达叶子并且函数调用开始返回时,这些变量将再次从堆栈中取出。
通常这不应该是问题,但是如果你的树有很多级别,你可能需要考虑堆栈的使用。
如果您假设一个空堆栈开始并查看第一个要销毁左侧的调用,您将拥有:
stack = | first left |
现在这可能导致另一个左边的呼叫:
stack = | first left |第二个左边|
甚至第三次打电话给左边:
stack = | first left |第二个左边第三个左边|
现在对第三个左边的调用返回:
stack = | first left |第二个左边|
但是权利将被称为:
stack = | first left |第二个左边第一个权利|
这个权利左边可能有一个节点,所以我们得到:
stack = | first left |第二个左边第一个权利|第一个离开|
并且这将继续,直到所有节点都返回 - 像这样
stack = | first left |第二个左边第一个权利|
stack = | first left |第二个左边|
stack = | first left |
stack =
现在是时候从右侧的顶部做同样的事了
stack = | first right |
依旧......
对于代码中的简单示例,它很可能会导致将4字节的返回地址推送到树中每个级别的堆栈。因此,即使树层相当深,堆栈的使用率也会很低。
答案 1 :(得分:0)
你必须拿一张纸来形象化它,但是,它们是顺序的,在树上的两个地方没有相同的节点,否则你会遇到问题。
它会像
destroy(root)
>destroy(l)
>l
>l
(...)
>r
(...)
>r
>l
(...)
>r
(...)
>delete root
>end
因此,您将开始在地址上推送地址,直到您最终到达分支的末尾,然后您弹出一次,并继续探索直到下一个分支的结束,依此类推。最后,在最后一个分支上,您将弹出所有函数,直到返回到原始函数,然后删除根节点。