【问题标题】:Stack overflow in my recursive function, is it due to logic or large number?我的递归函数中的堆栈溢出,是由于逻辑还是大量?
【发布时间】:2014-12-14 04:45:32
【问题描述】:

当我在一个小数组上运行我的函数时,它运行良好。然而,当我使用一个大数组时,我不断得到堆栈溢出。 是因为我的代码中的逻辑不正确吗?还是只是需要很长时间?

void RecursiveSort(T data[], int first, B last)
{

    // Sorts the array elements a[first] through a[last] recursively.

    // base case is if first and last are the same, which means we 
    // have no subarrays left to do



    if (first < last)
    {
        int minIndex = first;
        // replace first index of array with smallest of values in  the array 

        for (int index = first+1; index < last; index++)
        {
            if (data[index] < data[minIndex])
                // swap values
                minIndex = index;
        }   


        int temp = data[first];
        data[first] = data[minIndex];
        data[minIndex] = temp;



        RecursiveSort(data, first + 1, last);

    }


}

【问题讨论】:

  • 我不认为 sorter 从递归函数调用中受益。

标签: c++ recursion stack-overflow


【解决方案1】:

您看到堆栈溢出错误只是因为您的堆栈大小有限。每次调用递归函数时,都会使用一定量的内存来存储一些值,例如要返回的地址、函数参数的值等。有关详细信息,请参阅 this Wikipedia article

根据经验,如果您的递归深度超过 1000 级,您可能会遇到麻烦。

好消息是您的代码是 tail recursion 的示例,其中递归调用是函数中的最后一条语句。这样的函数可以很容易地转换为循环:

for (first = 0; first < last; ++first) {
     ...
}

或者,如果你真的需要创建递归排序,不要尝试实现选择排序,而是看Quicksortmerge sort,两者都可以使用递归来实现。

【讨论】:

    【解决方案2】:

    您的程序的堆栈内存有限。这个内存有多大可能取决于你的编译器或你的操作系统。

    对于递归函数的每次调用,函数的所有参数都放在堆栈上。这意味着每次调用都会占用另一块大小 (last - first)*sizeof(T)。

    使用大数组(最后 - 第一个)会更大,但这也意味着您的递归函数将被调用更多次。

    总共需要大约 (last - first)*(last - first)*sizeof(T)/2 + (last - first)*2*sizeof(int) 的堆栈大小。查看该公式,您可以看到当数组大小增加时,您的堆栈是如何出现问题的。

    【讨论】:

    • 它不会为每次调用复制整个数组,它只会每次传递指针(据我了解,作者在这里使用的是常规 C++ 数组,而不是 STL 容器,所以它被传递通过指针)。
    • 哎呀,是的,你是对的,数组被复制为指针,所以总堆栈大小将是 (last - first)*(sizeof(void *) + 2*sizeof(int))
    • ... 加上一些用于返回地址的内存,以及用于minIndexindextemp 等局部变量,它们也应该保存在堆栈中框架。我只想说它将使用 O(N) 的内存。
    • 是的,O(N) 是堆栈使用的正确关系。在我的回复中,我错误地得到了 O(N^2),因为我假设整个数组都放在了堆栈上。
    【解决方案3】:

    是的, 我也同意您将拥有有限的堆栈内存,但您可以通过放置如下所述的 SWAP 标志来减少递归调用。

    void recursive_bubble_sort(int *array, int size)
    {
       bool swap = false;   // to avoid recursion call when no swapping is required
       for(int i=0; i+1 < size; ++i)
       {
          if(array[i] < array[i+1])
          {
             int tmp = array[i];
             array[i] = array[i+1];
             array[i+1] = tmp;
    
             swap = true;
          }
       }
    
       if(swap)
          recursive_bubble_sort(array, size);
    }
    

    或者使用递归实现快速排序或合并排序以减少堆栈。

    【讨论】:

      猜你喜欢
      • 2015-01-06
      • 2018-07-24
      • 2017-10-20
      • 1970-01-01
      • 1970-01-01
      • 2019-12-21
      • 2013-04-05
      • 2016-03-22
      相关资源
      最近更新 更多