合并排序中的堆栈溢出

时间:2014-11-28 14:59:31

标签: c++ sorting

我有家庭作业,通过递归在C ++中实现合并排序。我并不擅长递归,接下来是我实现的代码,但它给出了stackoverflow错误。 请告诉我我做错了什么。编辑版

    #include<iostream>
using namespace std;
void divide(int A[], int n);
void sort();
int main(){
    int A[4]={2,3,0,5};
    divide(A, 4);
    for(int i =0 ;i<4;i++)
        cout<<A[i]<<endl;
    getchar();
}
void divide(int A[], int n){
    if(n<=2 && n>=1){
        for(int i=0; i<n; i++)
                if(A[i]>A[i+1]){

                int temp=A[i];
                A[i]= A[i+1];
                A[i+1]=temp;

                }
    }
    else{
    divide(A, n/2);
    divide(A,(n/2)+1 );
    }

}

在上面的代码中,n是要排序的元素数量,A是我排序的数组。

3 个答案:

答案 0 :(得分:1)

使用

调用以下代码
divide(A, 1);

应说明问题

void divide(int A[], int n){
    if(n==2){ // first time n==1 so no, further calls are n==0 so also no.
        for(int i=0; i<2; i++)
            if(A[i]>A[i+1]){
                int temp=A[i];
                A[i]= A[i+1];
            }
    } else{
        divide(A, n/2); // for both n==1 and n== 0 => n==0, calls divide(A, 0)
        divide(A,(n/2)+1 ); // calls divide(A, 1) always 
    }
}

因此,程序将永远调用除(A,0),直到内存不足为止。

要停止这种永恒的递归,你需要一个正确的停止条件

if (n<=2) {
    // correct code for swapping 1 or 2 elements
}  else

您还可以检查n的错误值,即0,负数且大于A的长度。


假设您有A [] = {1,2,3},请致电

divide(A, 3);

现在在程序的else部分,你需要将A分成部分,N / 2个元素和其余部分。

divide(A, n/2);

在我们的例子中,这给出了n / 2 = 3/2 = 1所以

除(A,1);

并从第n / 2个元素之后的元素开始

divide(A+(n/2), n-(n/2));

第一个元素是A [0],所以剩下的开始于A [1]并包含n-(n / 2)= 3-(3/2)= 3-1 = 2个元素。

现在是第一个if,它看起来像一个冒泡排序,但是因为它解决了超出数组末尾的元素而失败。

if(n<=2 && n>=1){
    for(int i=0; i<n; i++)
        if(A[i]>A[i+1]) { 

对于i = 1且n = 2,n = 2 =&gt; a [i + 1]超出数组的末尾。地址A [0]和A [1]的2个元素,因此A [i + 1] = A [2],它不是长度为2的数组A的一部分。

    for(int i=0; i<n-1; i++)

解决了这个问题并且还处理了n = 1的情况,这意味着数组只包含一个元素,根据定义它已经被排序了。

现在,如果算法被称为divide-sort,那么你将完成,但你仍然缺少合并部分。

答案 1 :(得分:1)

你仍然错过了合并。合并将需要第二个临时数组,我将其称为T并假设它从main传递:

void divide(int A[], int T[], int n){
    if(n < 2)
        return;
    if(n==2){
        // ... swap A[0], A[1] if needed (the existing code is ok)
        return;
    }
    divide(A, T, n/2);                   // recursively divide "left" half
    divide(A+(n/2), T+(n/2), n-(n/2));   // recursively divide "right" half
    merge(A, T, n/2, n)                  // merge the two halves
}

答案 2 :(得分:1)

假设分区0或1元素已经排序可能更简单。因此,将其作为停止条件就足够了

if (n < 2)
  return;