C ++中的Merge Sort实现问题

时间:2013-10-25 21:45:09

标签: c++ arrays sorting

我从伪代码实现算法时遇到两个错误:

我的一个问题是int L[n1+1];错误:需要是一个常数;不能分配常量大小0.运行它的唯一方法是使大小为10的数字。我可能正在实现伪的伪代码,这就是为什么我包含上面的语句。这可能是我下一个问题的原因。

我的另一个问题是我只打印了一行未排序的代码。我的打印功能完美无缺,适用于所有排序程序。我相信MERGE功能只运行一次。我在底部发布了Sort的输出。

我有一个数组A的随机数生成器,从0到RAND_MAX。 初始通话为MERGESORT(A,1,n);

void MERGE(int *A, int p, int q, int r)
{
    int n1 = q-(p+1);
    int n2 = r-q;

  //psuedocode states, let L[1..n1+1] & R[1..n1+1] be new arrays

    int L[n1+1];        
    int R[n2+1];    

    for(int i=1; i<n1;i++)
    {
        L[i]=A[p+(i-1)];
    }
    for(int j=1; j<n2; j++)
    {
        R[j] = A[q+j];
    }
    L[n1+1]=NULL; //sentinel
    R[n2+1]=NULL; //sentinel
    int i=1;
    int j=1;
    for (int k=p; k<r; k++)
    {
        if(L[i]<=R[j])
        {
            A[k]=L[i];
            i=i+1;
        }
        else
        {
            A[k]=R[j];
            j=j+1;
        }
    }
}

void MERGESORT(int *A,int p, int r)
{
    if (p<r)
    {
        int q=floor((p+r)/2);
        MERGESORT(A,p,q);
        MERGESORT(A,q+1,r);
        MERGE(A,p,q,r);
    }
}

使用int L[10];和我的A[10];我的输出是:

Sort:  7474 28268 32506 13774 14411
Press any key to continue . . .

如果有人可以帮助解决这两个问题,我很可能会让它发挥作用。

2 个答案:

答案 0 :(得分:3)

您未能检测到合并数组的结束:

for (int k=p; k<r; k++)
{

    // You need to check that i/j are still in range.
    // otherwise the following test are not valid.

    if ((i < n1) && (j < n2))
    {
      if(L[i]<=R[j])
      {
        A[k]=L[i];
        i=i+1;
      }
      else 
      {
        A[k]=R[j];
        j=j+1;
      }
    }
    else
    {   /* More work here */
    }

其他评论:

全都是MERGE MERGESORT的标识符通常用于宏。如果你使用它们,你可能会遇到问题。首选混合大小写的函数名称。

您可以使用vector:

模拟数组
// Simulate L[1..n1+1]
minI = 1;
maxI = n1-1;
std::vector<int> const L(A+(minI-1), A+(maxI-1));     

C ++中的数组是零索引的。你似乎有一个错误(特别是在访问数组的末尾)。我建议你在0而不是1开始计数。大多数C ++代码是用[begining..1PastEnd]的迭代器编写的。我认为如果你适应这种风格,你会发现你的算法更容易实现。

答案 1 :(得分:2)

您的代码存在一些问题,我在评论中指出了这些问题。这是一个最接近您的代码的解决方案,并且它是最好的。考虑使用C ++容器,例如std::vector。命名至少是有争议的,当然合并排序应该作为一种就地算法来实现。

//L and R are auxiliary arrays 
//preallocated with (inputSize/2 + 1) constant size
void MERGE(int *A, int p, int q, int r, int* L, int* R)
{
    if (p > q || q > r)
    {
        return;
    }

    int n1 = q - p + 1;
    int n2 = r - q;

    // note 0-based indices
    int i = 0;
    int j = 0;

    for(;i < n1;i++)
    {
        L[i] = A[p + i];
    }

    for(;j < n2;j++)
    {
        R[j] = A[q + j + 1];  //+1 because p + n1 - 1 == q + 0
    }

    //again - note 0-based indices
    i = 0;
    j = 0;

    for (int k = p; k <= r; ++k)
    {
        // The most important fix - in your code you didn't check
        // for left/right array bounds at all.
        // Sentinel values aren't needed - size is known
        if(i < n1 && (j >= n2 || L[i] <= R[j]))
        {
            A[k] = L[i];
            ++i;
        }
        else if (j < n2)
        {
            A[k] = R[j];
            ++j;
        }
    }
}

void MERGESORT(int* A, int p, int r, int* L, int* R)
{
    if (p < r)
    {
        int q = (p + r) / 2;  //floor was redundant
        MERGESORT(A, p, q, L, R);
        MERGESORT(A, q+1, r, L, R);

        MERGE(A, p, q, r, L, R);
    }
}

void MERGESORT(int* A, int size)
{
    int*L = new int[size/2 + 1]; //preallocate auxiliary arrays
    int*R = new int[size/2 + 1]; //size/2 + 1 is what will be needed at most

    MERGESORT(A, 0, size - 1, L, R);

    delete L;
    delete R;
}

int main()
{
    int A[5]{ 7474, 28268, 32506, 13774, 14411 };

    MERGESORT(A, 5);

    for (int i = 0;i < 5;++i)
    {
        std::cout << A[i] << std::endl;
    }

    return 0;
}

输出:

7474
13774
14411
28268
32506

还可以通过DyP来查看以前版本中的所有错误:)