我有家庭作业,通过递归在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
是我排序的数组。
答案 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;