我的C ++合并排序程序有什么问题?

时间:2012-03-21 00:33:20

标签: c++ arrays algorithm sorting mergesort

我对这个实现感到困惑。在合并子阵列的过程中,我的n2变量被覆盖了,这可能导致什么?我尝试过硬编码值,但似乎没有用。

#include <iostream>
#include <cstdlib>
#include <ctime> // For time(), time(0) returns the integer number of seconds from the     system clock
#include <iomanip>
#include <algorithm> 
#include <cmath>//added last nite 3/18/12 1:14am

using namespace std;

int size = 0;

void Merge(int A[], int p, int q, int r)
{
    int i,
        j,
        k,
        n1 = q - p + 1,
        n2 = r - q;

    int L[5], R[5];

    for(i = 0; i < n1; i++)
        L[i] = A[i];

    for(j = 0; j < n2; j++)
        R[j] = A[q + j + 1];

    for(k = 0, i = 0, j = 0; i < n1  && j < n2; k++)//for(k = p,i = j = 1; k <= r; k++)
    {
        if(L[i] <= R[j])//if(L[i] <= R[j])
        {
            A[k] = L[i++];
        } else {
            A[k] = R[j++];
        }
    }
}

void Merge_Sort(int A[], int p, int r)
{
    if(p < r)
    {
        int q = 0;
        q = (p + r) / 2;
        Merge_Sort(A, p, q);
        Merge_Sort(A, q+1, r);
        Merge(A, p, q, r);
    }
}

void main()
{
    int p = 1,
        A[8];

    for (int i = 0;i < 8;i++) {
        A[i] = rand();
    }
    for(int l = 0;l < 8;l++)
    {
        cout<<A[l]<<"  \n";
    }
    cout<<"Enter the amount you wish to absorb from host array\n\n";
    cin>>size;
    cout<<"\n";
    int r = size; //new addition
    Merge_Sort(A, p, size - 1);

    for(int kl = 0;kl < size;kl++)
    {
        cout<<A[kl]<<"  \n";
    }

}

3 个答案:

答案 0 :(得分:1)

您使用什么工具来编译程序?在e,.g中有一些标志可以打开这种东西的检查。 gcc(例如-fmudflap,我还没有使用它,但它看起来很有用)。

如果你可以使用调试器(例如gdb),你应​​该可以添加一个数据监视器&#39;对于变量n2,调试器将在检测到写入n2的任何内容时停止程序。这应该可以帮助您追踪错误。或者尝试valgrind

暂时停止此类错误的一种简单方法是在被删除的虚拟变量周围添加一些虚拟变量,所以:

int dummy1[100];
int n2 = r - q;
int dummy2[100];

int L[5], R[5];

被破坏的变量通常是由超出数组边界的代码编写引起的。 罪魁祸首可能是R[5],因为这可能是最接近的。您可以查看虚拟对象以查看正在编写的内容,并且可以从中发现正在发生的事情。

另一个选择是在追踪问题的同时使所有阵列变得庞大。再次将超出正确边界的值设置为已知值,并检查那些应该保持不变的值。

您可以制作一个小宏来进行这些检查,并将其放在任何方便的地方。

答案 1 :(得分:1)

我之前使用过类似的Merge功能,但它似乎无法正常工作。然后我重新设计,现在它完美无缺。下面是C ++中合并函数的重新设计的函数定义。

void merge(int a[], int p, int q, int r){
    int n1 = q-p+1;             //no of elements in first half
    int n2 = r-q;               //no of elements in second half
    int i, j, k;

    int * b = new int[n1+n2];   //temporary array to store merged elements

    i = p;
    j = q+1;
    k = 0;
    while(i<(p+n1) && j < (q+1+n2)){     //merging the two sorted arrays into one
        if( a[i] <= a[j]){
            b[k++] = a[i++];
        }
        else 
            b[k++] = a[j++];
    }

    if(i >= (p+n1))         //checking first which sorted array is finished
        while(k < (n1+n2))      //and then store the remaining element of other 
            b[k++] = a[j++];    //array at the end of merged array.
    else
        while(k < (n1+n2))
            b[k++] = a[i++];

    for(i = p,j=0;i<= r;){      //store the temporary merged array at appropriate  
        a[i++] = b[j++];        //location in main array.
    }

    delete [] b;
}

我希望它有所帮助。

答案 2 :(得分:0)

void Merge(int A[], int p, int q, int r)
{
    int i,
        j,
        k,
        n1 = q - p + 1,
        n2 = r - q;

    int L[5], R[5];

    for(i = 0; i < n1; i++)
        L[i] = A[i];

您只需分配L[5],但您使用的n1界限基于输入qp - 并允许调用方调用该函数值qp允许在L[]范围之外书写。这可以表现为覆盖任何其他自动变量,但由于它是未定义的行为,几乎任何事情都可能发生。 (包括security vulnerabilities。)

我不知道解决这个问题的最佳方法是什么 - 我不明白为什么你在Merge()中有固定长度的缓冲区,我没有仔细阅读以找出原因 - 但是当L[i]大于或等于i时,您不应该访问5

整个对话也适用于R[]。并且,由于*A被传递给Merge(),因此确保您的数组访问也始终处于绑定状态是有意义的。 (我没有发现它们超出界限,但由于此代码需要重新工作,我不确定值得我仔细查找它们。)