合并排序不完全正常

时间:2013-07-31 07:02:02

标签: c++ arrays sorting mergesort

我为合并排序所做的代码如下。问题是,在输入时输出 3 2 1 5 0 。出了什么问题?

#include <iostream>
#include <cmath>
using namespace std;

int d[100];

void merge(int a[], int b[], int c[], int n)
{
int n2=floor(n/2);
int i=0, j=0, k=0;
while(i<n2 && j<(n-n2))
{
    if(b[i]<c[j])
    {
        d[k++]=b[i++];
    }
    else if(b[i]>c[j])
    {
        d[k++]=c[j++];
    }
}
    if(i==n2)
    {
        if(j<(n-n2))
        {
            d[k++]=c[j++];
        }
    }
    if(i<n2)
    {
        d[k++]=b[i++];
    }
}


void mergesort(int a[], int n)
{
int n2=floor(n/2);
int b[50],c[50];
int i,j=0,k=0;
for(i=0;i<n2;i++)
{
    b[i]=a[k++];
}
while(k<n)
{
    c[j++]=a[k++];
}
merge(a,b,c,n);
}

int main()
{
int a[]={5,4,3,2,1};
int n=5;
mergesort(a,n);
for(int i=0;i<n;i++)
{
    cout<<d[i]<<endl;
}
}

5 个答案:

答案 0 :(得分:4)

主要问题是传递给merge的数组(b和c)没有排序。 其他问题是该算法不是递归的并且是合并的 并不总是将b和c中的所有数字都放入。

似乎对代码进行最少更改的版本

void merge(int a[], int b[], int c[], int n)
{
  int n2=floor(n/2);
  int i=0, j=0, k=0;
  while(k<n)
  {
    if((j == (n-n2) || b[i]<c[j]) && i < n2)
    {
      a[k++]=b[i++];
    }
    else
    {
      a[k++]=c[j++];
    }
  }
}


void mergesort(int a[], int n)
{
  int n2=floor(n/2);
  int b[50],c[50];
  int i,j=0,k=0;
  for(i=0;i<n2;i++)
  {
    b[i]=a[k++];
  }
  while(k<n)
  {
    c[j++]=a[k++];
  }
  if(n2 > 1) {
    mergesort(b, n2);
  }
  if(n - n2 > 1) {
    mergesort(c, n - n2);
  }
  merge(a,b,c,n);
}

int main()
{
  int a[]={5,4,3,2,1};
  int n=5;
  mergesort(a,n);
  for(int i=0;i<n;i++)
  {
    cout<<a[i]<<endl;
  }
}

答案 1 :(得分:2)

通常以递归方式调用merge_sort,以便对每个子范围进行排序,直到子范围只有一个,然后将它们合并在一起。

mergesort中,ba的前n / 2个值,即5和4。 c取剩余值3,2,1。

然后你拨打merge(BTW为什么你将a[]传递给它?它没有被使用) 第一个循环

while(i<n2 && j<(n-n2))

n2 = 2n-n2 = 5-2 = 3 由于类似原因,自b[0]>c[0]=3以来开始有3个,自b[1]>c[1]=2后有2个,d[2]有1个。 由于你没有递归,你不会对这些进行排序。 然后用i = 0完成while循环,小于n2。 你只是说

if(i<n2)

所以你只需复制b中的第一个东西,即5。

所有这一切都给出了3分,2分,1分,5分和0分,因为你将d设为全局。

答案 2 :(得分:1)

合并的输入需要是排序数组,正如Philip之前提到的那样。 Mergesort是递归的。为此,您需要将它们分开,直到达到数组中只有一个元素的位置(因此对其进行排序)并合并所有数组以成为输入的排序结果。维基百科是您理解算法的朋友:Mergesort

顺便说一下:您需要确保合并中比较中的两个案例中的一个还检查值的相等性。

答案 3 :(得分:0)

菲利普是对的,你的代码中根本没有递归

然而,还有一些错误。我用注释标记了它,就像菲利普的后记一样。

#include <iostream>
#include <cmath>
using namespace std;

int d[100];

void merge(int a[], int b[], int c[], int n)
{
    int n2=floor(n/2);
    int i=0, j=0, k=0;
    while(i<n2 && j<(n-n2))
    {
        if(b[i]<c[j])
        {
            d[k++]=b[i++];
        }
        else if(b[i]>c[j])
        {
            d[k++]=c[j++];
        }
        /***************************************************/
        /* What if b[i] == c[j] here?                      */
        /* Your code will drop into an infinity loop.      */
        /***************************************************/
    }
    if(i==n2)
    {
        if(j<(n-n2))
        /****************************************************/
        /* Use **while** here?                              */
        /* Because there may be more than one elements left */
        /* in c[].                                          */
        /****************************************************/
        {
            d[k++]=c[j++];
        }
    }
    if(i<n2)
    /***************************************************/
    /* Use **while** here? - With the same reason      */
    /***************************************************/
    {
        d[k++]=b[i++];
    }
}


void mergesort(int a[], int n)
{
    int n2=floor(n/2);
    int b[50],c[50];
    int i,j=0,k=0;
    for(i=0;i<n2;i++)
    {
        b[i]=a[k++];
    }
    while(k<n)
    {
        c[j++]=a[k++];
    }
    merge(a,b,c,n);
}

int main()
{
    int a[]={5,4,3,2,1};
    int n=5;
    mergesort(a,n);
    for(int i=0;i<n;i++)
    {
        cout<<d[i]<<endl;
    }
}

答案 4 :(得分:0)

template <typename T>
void merge(T arr[], int begin, int mid, int end)
{
    int len = end - begin;
    T *temp = new T[len];
    int i = begin;
    int j = mid + 1;
    int k = 0;
    while (i <= mid && j <= end)
    {
        if(arr[i] <= arr[j])
            temp[k++] = arr[i++];
        else
            temp[k++] = arr[j++];
    }
    while (i <= mid)
        temp[k++] = arr[i++];
    while(j <= end)
        temp[k++] = arr[j++];

    memcpy(arr + begin, temp, len*sizeof(T));
    delete []temp;
}
template <typename T>
void mergeSort(T arr[], int begin, int end)
{
    if (begin >= end)
        return;

    int mid = (end + begin) / 2;
    mergeSort(arr, begin, mid);
    mergeSort(arr, mid + 1, end);
    merge(arr, begin, mid, end);
}