问题描述
我试图从 clrs 书中的伪代码中实现这一点,但我失败了。 我正在尝试使用迭代器编写合并排序,以在 c 语言中实现自己的伪代码,但由于某种原因,此代码正在编译但结果未排序。有人能弄清楚它有什么问题吗?对我未经训练的眼睛来说,这似乎完全没问题。
#include <stdio.h>
#include<math.h>
#include <stdlib.h>
int a[] = {5,3,65,6,7,8};
void print_array(int a[],int size)
{
int i;
for(i = 0;i < size;i++)
{
printf("%d ",a[i]);
}
}
void merge(int a[],int p,int q,int r)
{
int n1,n2,i,j,k;
n1 = q - p + 1;
n2 = r - q;
int l[n1];
int m[n2];
for(i = 0; i < n1; i++)
l[i] = a[i+p];
for(j = 0; j < n2; j++)
m[j] = a[q+1+j];
l[n1] = 9999999;
m[n2] = 9999999;
i = 0;
j = 0;
for(k = p;k < r; k++)
{
if(l[i] <= m[j])
{
a[k] = l[i];
i = i+1;
}
else
{
a[k] = m[j];
j = j+1;
}
}
}
void merge_sort(int a[],int r)
{
if(p < r)
{
int q = floor((p + r) / 2);
merge_sort(a,p,q);
merge_sort(a,q+1,r);
merge(a,q,r);
}
}
int main()
{
int size = (sizeof(a) / sizeof(a[0]));
print_array(a,size);
printf("\n");
merge_sort(a,size);
print_array(a,size);
return 0;
}
//for this input out put is showing
//-1 -1 3 3 3 -1 6 7
解决方法
请注意数组的边界和大小:
-
你的参数
r
不是数组的大小,而是最右边元素的索引,所以你应该调用merge_sort(a,size - 1);
。 -
当你想使用一个大的哨兵值时,在实际数组之后,你必须为它分配空间,所以:
int l[n1]; int m[n2];
-
因为你的值
r
是最后一个元素的索引,所以在合并的时候一定要考虑,你的循环条件应该是for(k = p; k <= r; k++)
。 -
(其实不是问题,但您不需要像在 JavaScript 中那样使用
floor
。当a
和b
是整数时,a / b
会执行结果为整数的除法。)
在 C 中,数组(以及一般的范围)具有包含下限和不包含上限:lo
是第一个有效索引,hi
是有效范围之后的第一个无效索引。对于数组索引,lo
和 hi
为零和数组大小。
接受这个约定。 C 索引导致以下样式:
- 范围的长度为
hi - lo
; - 前向循环是
for (i = lo; i < hi; i++)
; - 相邻范围共享
hi
和lo
值。
例如,在您的 merge
函数中,中间值 p
将是右侧范围的第一个值,也是左侧范围的唯一上限。
如果伪代码或其他语言的代码使用从一开始的索引,我建议将其翻译成 C 的从零开始的排他上界风格。一段时间后,您会怀疑虚假的 - 1
和 <=
。 :)