【问题标题】:Merge sort in CC中的合并排序
【发布时间】:2015-03-27 04:16:22
【问题描述】:

我是编程/C 方面的新手。 我将合并排序算法理解为一种算法,但是在编程方面,似乎我做错了什么。 有人可以帮忙吗?

谢谢。

这是我的代码:

merge(int A[],int p,int q,int r);
part(int A[],int p,int r);

int main()
{
int A [6]={10,5,4,0,11,7}, n,y,z;

y=1; z=sizeof(A)/sizeof(int);

part(A,y,z);
for(n=0;n<z;n++)
printf("%d\n", A[n]);

    return 0;
}

part(int A[],int p,int r)
{
    if (p<r)
    {
        int q=(p+r)/2;
        part(A,p,q);
        part(A,q+1,r);
        merge(A,p,q,r);
    }
}

merge(int A[],int p,int q,int r)
{
    int n1=q-r+1,n2=r-q,L[n1+1],R[n2+1],i,j,k;
    L[n1+1]=100000;
    R[n2+1]=100000;
    for (i=0;i<n1;i++)
        L[i]=A[p-1+i];
    for (j=0;j<n2;j++)
        R[j]=A[q+j];
    i=0;j=0;
    for (k=0;k<r;k++)
        if(L[i]<=R[j])
    {
        A[k]=L[i];
        i++;
    }
    else
    {
        A[k]=R[j];
        j++;
    }
}

【问题讨论】:

  • it appears that I am doing something wrong. 发生了什么让你这么认为?
  • 你是怎么得出I am doing something wrong这个结论的?
  • 您可以从指定函数的返回类型开始。
  • 首先:数组,在 C 中,索引从 0n - 1。定义为 int L[n1 + 1]; 的数组具有 (n1 + 1) 元素,其索引为 0n1。元素 L[n1 + 1] 不存在......但您尝试写入它。
  • 对于所有讽刺的 cmets what happens that makes you think so?, How you came to this conclusion - 如果 OP 知道这个问题的答案,就永远不会问这个问题。 OP 试图解决一个问题并发布了有问题的工作。如果你不能回答问题,那么至少不要降低 SO 的标准。我希望 SO 在这里作为有经验的用户回答此类问题。反对者也是如此。我们确切地知道合并排序应该做什么。

标签: c algorithm mergesort


【解决方案1】:

这是您更正后的代码:

#include<stdio.h>
#include<limits.h>

void merge(int A[],int p,int q,int r);
void part(int A[],int p,int r);

int main()
{
int A [6]={10,5,4,0,11,7}, n,y,z;

y=0; z=6;

part(A,0,z-1); // Pass starting from 0 to Length - 1 of Array
for(n=0;n<z;n++)
printf("%d\n", A[n]);

    return 0;
}

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

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

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

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

    i=0;j=0;

    for (k=p;k<=r;k++)
    {
        if(L[i]<=R[j])
        {
            A[k]=L[i];
            i++;
        }
        else
        {
            A[k]=R[j];
            j++;
        }
    }
}

这些是错误的部分:

int n1=q-r+1,n2=r-q  // --> Your calculation of new indices was wrong

这些索引将您带出数组的边界:

L[n1+1]=100000;
R[n2+1]=100000;

另外,不要使用100000 之类的随机值,而是使用limits.h 中的INT_MAX 作为标记元素。

 for (k=0;k<r;k++) // ->wrong

您应该从数组的左侧索引移动到右侧,而不是从0th 索引。

输出:

0
4
5
7
10
11

你可以自己检查。

【讨论】:

  • 代码不工作——这强烈表明我做错了什么。谢谢al-Acme
【解决方案2】:

零件参数为 0 到数组大小的替代解决方案。我的旧 C 编译器不支持可变大小的数组,所以我使用 _alloca() 作为替代。其他替代方法是传递第二个数组以用作合并排序的临时数组,以及自上而下或自下而上的合并排序。复制操作可以通过根据递归级别交替合并方向来避免自上而下的复制操作,并使用一对协同递归函数:顶层是 partAtoA(),它将调用 partAtoB()(它将调用 partAtoA(), ...)。

#include <stddef.h>
#include <stdio.h>

void merge(int A[],int p,int q,int r);
void part(int A[],int p,int r);

int main()
{
int A[6]={10,5,4,0,11,7}, n,y,z;
    y=0;
    z=sizeof(A)/sizeof(int);
    part(A,y,z);
    for(n=0;n<z;n++)
        printf("%d\n", A[n]);
    return 0;
}

void part(int A[], int p, int r)
{
int q;
    if ((r - p) < 2)
        return;
    q=(p+r)/2;
    part(A,p,q);
    part(A,q,r);
    merge(A,p,q,r);
}

void merge(int A[],int p,int q,int r)
{
int n1=q-p, n2=r-q;
int i,j,k;
/* using _alloca for variable size arrays */
int * L = _alloca(n1*sizeof(int));
int * R = _alloca(n2*sizeof(int));
    for (i=0; i<n1; i++)
        L[i]=A[p+i];
    for (j=0; j<n2; j++)
        R[j]=A[q+j];
    i=0;j=0;
    for(k=p;k<r;k++)
        if(j>=n2 || i<n1 && L[i]<=R[j])
            A[k]=L[i++];
        else
            A[k]=R[j++];
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-06
    • 1970-01-01
    • 2019-03-17
    • 2011-02-09
    • 2013-03-27
    • 2014-01-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多