Performance 递归与手动堆栈-在哪种情况下首选哪种?

Performance 递归与手动堆栈-在哪种情况下首选哪种?,performance,data-structures,recursion,stack,recursive-datastructures,Performance,Data Structures,Recursion,Stack,Recursive Datastructures,递归程序在内部创建堆栈,并使用户编写更少的代码 除了上面提到的原因之外,是否有任何情况下递归实际上比手动堆栈更受欢迎 编辑1: 动态内存分配在哪些方面比递归程序在堆上的分配更“昂贵”?主要原因是设计的清晰性和简单性,我想你在说“更少的代码”时提到了这一点。在一种具有局部变量和自动存储等特性的语言中,使用这些特性比将所有内容组织成本地堆栈要自然得多。(毕竟,为什么要使用函数呢?为什么不使用if/else和while作为唯一的控制结构来编写整个程序呢?) 另一个考虑因素是性能,特别是在多线程环境中。

递归程序在内部创建堆栈,并使用户编写更少的代码

除了上面提到的原因之外,是否有任何情况下递归实际上比手动堆栈更受欢迎

编辑1:
动态内存分配在哪些方面比递归程序在堆上的分配更“昂贵”?

主要原因是设计的清晰性和简单性,我想你在说“更少的代码”时提到了这一点。在一种具有局部变量和自动存储等特性的语言中,使用这些特性比将所有内容组织成本地堆栈要自然得多。(毕竟,为什么要使用函数呢?为什么不使用
if
/
else
while
作为唯一的控制结构来编写整个程序呢?)


另一个考虑因素是性能,特别是在多线程环境中。递归-取决于语言-可能会使用(注意:您说“在内部创建堆栈”,但实际上,它使用的堆栈通常是这种语言中的程序所拥有的),而手动堆栈结构需要,这通常会带来明显的性能损失——更不用说在遇到异常时确保释放所有内存的复杂性了。

我基本上同意@ruakh的答案。我只想补充一点,使用系统堆栈会有很大的开销(实际上,每次递归时,所推的状态比需要的多得多),并且可能会导致非常深(但有界)递归的堆栈溢出,您可以通过使用显式堆栈并仅推送所需的状态来避免这种情况。

使用外部堆栈

vector<int> Solution::inorderTraversal(TreeNode* A) {
vector<int> res;
stack<TreeNode* > st;
TreeNode* root=A;
while(true)
{
    if(root==NULL)
    {
        if(st.empty())
        break;
        root=st.top();
        st.pop();
        res.push_back(root->val);
        root=root->right;


    }
    else
    {

        st.push(root);
        root=root->left;
    }
}
return res;

但是在这里,我们看到外部使用堆栈可以节省大量的处理时间,因此外部堆栈方法更快。

使用系统堆栈的性能权衡是,通常系统堆栈的递归深度比堆上的堆栈数据结构要有限得多,因为堆要大得多。
而手动堆栈结构需要动态内存分配,这通常会造成明显的性能损失,这是一个要点。但是重复的函数调用不是性能损失吗?它不是比手动内存分配更大吗?@SethCarnegie:是的,绝对是,很好。在许多平台上,堆内存耗尽比堆栈溢出更容易处理。由于问题严格地说是关于使用递归的原因,我没有提到这些东西,但无论如何,为了完整性,也许我应该这样做?@AnishaKaul:一如既往,如果性能达到这种程度,那么你需要在你关心的平台上测试它;但一般来说——如果使用链表作为堆栈,那么我认为动态内存分配比重复函数调用更昂贵,但是如果使用可动态调整大小的数组并从末尾添加/删除元素,然后,您很可能会将动态内存分配的数量减少到非常便宜的程度。然而,问题是,如果你的目标是消除重复的函数调用,那么,你要做什么?动态内存分配会“昂贵”吗?不是仅仅关于分配和释放内存吗?Mac,请看我对ruakh答案的评论。void inorder(struct node*root){if(root!=NULL){inorder(root->left);coutright);}}如果递归没有超过堆栈大小,那么您只使用调用堆栈,而不是堆。
void inorder(struct node* root)