我的C++合并排序程序出了什么问题

What is wrong with my C++ merge sort program?

本文关键字:什么 问题 程序 C++ 合并 排序 我的      更新时间:2023-10-16

我在这个实现上陷入了困境。在合并子数组的过程中,我的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 arraynn";
    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";
    }
}

您使用哪些工具来编译程序?在例如gcc中,有一些标志可以打开对这类事情的检查(例如-fmudflap,我没有使用过,但它看起来很有用)。

如果你可以使用调试器(例如gdb),你应该能够为变量n2添加一个"数据监视",每当调试器检测到有任何东西写入n2时,它就会停止程序。这应该有助于您追踪错误。或者试试valgrind。

暂时停止这种类型错误的一个简单技术是在被破坏的变量周围放置一些伪变量,因此:

int dummy1[100];
int n2 = r - q;
int dummy2[100];
int L[5], R[5];

被丢弃的变量通常是由超出数组范围的代码写入引起的。罪魁祸首很可能是R[5],因为它可能是最接近的。你可以看看假人,看看写的是什么,并可能从中推断出发生了什么。

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

你可以制作一个小宏来进行这些检查,然后把它放在任何方便的地方。

我之前使用过类似的Merge函数,但它似乎无法正常工作。然后我重新设计,现在它运行得非常好。下面是C++中为merge函数重新设计的函数定义。

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;
}

我希望它能有所帮助。

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[]的边界之外进行写入。这可能表现为重写任何其他自动变量,但由于这是未定义的行为,几乎任何事情都可能发生。(包括安全漏洞。)

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

整个对话也适用于R[]。而且,由于*A被传递给Merge(),因此确保对它的数组访问也始终处于绑定状态是有意义的。(我还没有发现它们越界,但由于这段代码无论如何都需要重新处理,我不确定是否值得我仔细寻找它们。)