实现大型数组的合并排序时出现bad_alloc异常

时间:2014-11-29 02:44:18

标签: c++ arrays sorting mergesort bad-alloc

我正在使用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++;
                }
        }
}

如果有人可以告诉我这背后的原因而不是修复,那会更好。谢谢!

1 个答案:

答案 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[]