我为合并排序所做的代码如下。问题是,在输入时输出 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;
}
}
答案 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
中,b
取a
的前n / 2个值,即5和4。
c
取剩余值3,2,1。
然后你拨打merge
(BTW为什么你将a[]
传递给它?它没有被使用)
第一个循环
while(i<n2 && j<(n-n2))
将n2 = 2
和n-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);
}