堆栈是如何组织的? :删除二叉树

时间:2015-04-04 01:36:23

标签: c++ recursion binary-tree stack-trace

我有这段代码从内存中删除二进制树,但是当你对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;
    }
}

2 个答案:

答案 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

因此,您将开始在地址上推送地址,直到您最终到达分支的末尾,然后您弹出一次,并继续探索直到下一个分支的结束,依此类推。最后,在最后一个分支上,您将弹出所有函数,直到返回到原始函数,然后删除根节点。