我正在使用C ++实现合并排序算法。引发异常(bad_alloc),同时对较大的数组进行排序。由于我是C ++的新手,我不知道如何摆脱这个错误。我愿意的答案不是处理异常,而是原因。
这是我最初调用merge_sort函数的主要方法。
int *arr;
int main(){
int limits[2]={10,10000000}; //numbers of elements that should be in an array at each iteration
for(int l=0;l<sizeof(limits)/sizeof(*limits);l++){
cout<<"\n"<<endl;
arr=new int[limits[l]];
for(int cnt=0;cnt<limits[l];cnt++){ //creating the random array using random numbers
int temp=rand()%2147483647;
arr[cnt]=temp;
}
clock_t t;
t=clock();
cout<<"\nNumber of elements : "<<limits[l]<<endl;
merge_sort(0,limits[l]-1); //calling the merge sort function
cout<<endl;
t=clock()-t;
cout<<"The time taken : "<<t<<endl;
delete[] arr;
}
cin.get();
return 0;
}
最多1000000个元素可以正常工作。我在排序大小为10000000的数组时遇到了麻烦。
以下是测试目的的完整代码。
#include<iostream>
#include<string.h>
#include<limits>
#include<time.h>
#include<stdlib.h>
using namespace std;
void merge_sort(int i,int j);
void merge(int i,int temp,int j);
int *arr;
//main method
int main(){
int limits[2]={10,10000000}; //numbers of elements that should be in an array at each iteration
for(int l=0;l<sizeof(limits)/sizeof(*limits);l++){
cout<<"\n"<<endl;
arr=new int[limits[l]];
for(int cnt=0;cnt<limits[l];cnt++){ //creating the random array using random numbers
int temp=rand()%2147483647;
arr[cnt]=temp;
}
clock_t t;
t=clock();
cout<<"\nNumber of elements : "<<limits[l]<<endl;
merge_sort(0,limits[l]-1); //calling the merge sort function
t=clock()-t;
cout<<"The time taken : "<<t<<endl;
delete[] arr;
}
cin.get();
return 0;
}
//method implementing the merge sort algorithm
void merge_sort(int i,int j){
if(i<j){
int temp=(i+j)/2;
merge_sort(i,temp);
merge_sort(temp+1,j);
merge(i,temp,j);
}
return;
}
//method implementing the merge algorithm
void merge(int i,int temp,int j){
int n1=temp-i+2; //calculating the sub array lengthes
int n2=j-temp+1;
int *L=NULL;
int *R=NULL;
L=new int[n1]; //dynamically initializing the sub left and right hand side arrays
R=new int[n2];
for(int x=0;x<n1-1;x++){
L[x]=arr[i+x];
}
for(int y=0;y<n2-1;y++){
R[y]=arr[temp+y+1];
}
L[n1-1]=numeric_limits<int>::max(); //adding the largest possible integer to the end of each array
R[n2-1]=numeric_limits<int>::max();
int a=0;
int b=0;
for(int k=i;k<=j;k++){ //merging the two sub arrays
if(L[b]>R[a] ){
arr[k]=R[a];
a++;
}
else{
arr[k]=L[b];
b++;
}
}
}
如果有人可以告诉我这背后的原因而不是修复,那会更好。谢谢!
答案 0 :(得分:0)
你的merge
函数有内存泄漏,而且非常大:
L = new int[n1];
R = new int[n2];
永远不会释放内存。如果您来自Java或C#等语言,您会发现C ++的工作方式不同。没有自动垃圾回收,在C ++中使用new[]
要求您在某个时候使用delete[]
,否则会出现内存泄漏。
但更好的解决方案是用这个替换这些线:
#include <vector>
//...
// Remove the int *L and int *R declarations.
//
std::vector<int> L(n1);
std::vector<int> R(n2);
您应该始终首先考虑vector
使用new[]/delete[]
来避免这些类型的内存错误。
完成这些更改后,程序将完成,但需要一段时间(至少在调试模式下使用Visual Studio 2013)。
在发布模式下,10000000的时间为3,300毫秒。
编辑:对于实验,我使用以下代码来查看如果向量移出函数会发生什么,并且只是重复使用:
std::vector<int> L;
std::vector<int> R;
void merge(int i, int temp, int j){
int n1 = temp - i + 2;
int n2 = j - temp + 1;
L.resize(n1);
R.resize(n2);
//...
}
所以我把矢量全局化了。它花费的时间接近2,000毫秒,因此快约1,000毫秒。优点是使用resize
来调整向量的大小,而不是重新定义它们,或者多次使用new[]/delete[]
。