[英]Stack overflow in merge sort
我有家庭作业,通过递归在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
是我正在排序的数组。
用以下代码调用以下代码
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,a [i + 1]超出数组的末尾,地址A [0]和A [1]的n = 2 => 2个元素,因此A [i + 1] = A [ 2]不是长度为2的阵列A的一部分。
for(int i=0; i<n-1; i++)
解决了这个问题并且还处理了n = 1的情况,这意味着该数组只包含一个元素,根据定义,该元素已经被排序。
现在,如果算法被称为divide-sort,那么你将完成,但你仍然缺少合并部分。
你还在错过合并。 合并将需要第二个临时数组,我将其称为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
}
假设分区0或1元素已经排序可能更简单。 因此,足以作为停止条件
if (n < 2)
return;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.