【发布时间】:2013-09-23 23:25:16
【问题描述】:
我正在尝试在 C 中实现归并排序算法。我了解该算法应该如何工作,但是我在实现时遇到了一些困难。
我知道它的实现有数百个示例和源代码,但我希望有人能帮助我理解为什么我的工作不正常。
我的代码在下面,在代码之后我解释了我到目前为止所做的尝试。
#include <stdio.h>
void merge(int a[], int L[], int R[],int nL, int nR) //nL and nR are the lengths of L[] and R[]
{
int i = 0 , j = 0, k = 0;
while(i<nL && j <nR)
{
if(L[i] <= R[j]){
a[k] = L[i];
i++;
}
else{
a[k] = R[j];
j++;
}
k++;
}
while(i < nL){
a[k] = L[i];
i++;
k++;
}
while(j < nR) {
a[k] = R[j];
j++;
k++;
}
}
void mergesort(int a[],int n) //n is the length of a[]
{
if(n < 2) return; //BASE CASE
int mid = n / 2;
int left[mid];
int right[n-mid];
for(int i = 0; i < mid; i++)
{
left[i] = a[i];
}
for(int i = mid; i < n-1; i++)
{
right[i-mid] = a[i];
}
int nL = sizeof(left) / sizeof(left[0]);
int nR = sizeof(right) / sizeof(right[0]);
mergesort(left, nL);
mergesort(right, nR);
merge(a,left,right,nL,nR);
}
int main(void)
{
printf("Initial:\n");
printf("3 4 1 6\n");
int numbers[4] = {3,4,1,6};
int n = sizeof(numbers) / sizeof(int);
mergesort(numbers,n);
printf("Sorted:\n");
for(int i =0 ; i < 4; i++)
{
printf("%d ", numbers[i]);
}
return 0;
}
原样和未排序的数组[3,4,1,6] 的输出是0 0 1 3。
显然 1 和 3 相对于彼此的顺序是正确的,但开头的两个零显然是错误的。起初,在我看来,我将 4 和 6 插入到数组的右侧并且超出了数组的范围。
我使用了一些打印语句来尝试调试,但我无法弄清楚发生了什么。我什至尝试使用 gdb 跟踪我的代码,但我仍然无法对其进行排序。
有人对可能发生的事情有任何想法吗?
【问题讨论】:
-
当您在调试器中运行它时,哪一行的行为与您的预期不同?
-
这不是问题所在,但您不需要
sizeof()计算。您已经知道每个子序列的长度:mid和n-mid。假设您的merge()算法是正确的(一个很大的假设),您的右侧副本不正确,那么更可能是什么问题。它应该运行到i < n,而不是i < n-1。 -
同意 WhozCraig 的观点,
for(int i = mid; i < n-1; i++)中的-1是不需要的。其余的,通过为自己提供一个函数void dump_array(const char *tag, int n, int *a) { printf("%d:", n); for (int i = 0; i < n; i++) printf("%s:%d:", a[i]); putchar('\n'); }并经常调用它来进行调试:在进入mergesort()(dump_array("enter", n, a);) 时,在创建左侧数组之后,在创建右侧数组之后,之后在合并结果后,您合并排序了左数组,合并排序了右数组。它将帮助您缩小问题范围。 -
我无法支持乔纳森的评论。在处理分区排序算法(如合并排序、快速排序等)时,为您转储可疑序列的调试例程几乎是强制性的,以帮助您在开发过程中检查自己。
-
哇:我的代码中有错别字——它们只能在 5 分钟内编辑。给自己提供一个函数
void dump_array(const char *tag, int n, int *a) { printf("%s:%d:", tag, n); for (int i = 0; i < n; i++) printf(" %3d", a[i]); putchar('\n'); }并经常调用它:在进入mergesort()(例如dump_array("-->>mergesort()", n, a);)时,创建左数组后,创建右数组后,合并排序后左数组,合并排序后合并结果后的正确数组 (dump_array("<<--mergesort()", n, a);)。它将帮助您缩小问题范围。
标签: c algorithm sorting mergesort