这段代码展示了我是如何检测算法的。最初,它是通过对printf() 和dump_array() 的无条件调用来完成的——当它工作时,它们被转换为宏,以便可以使用-DDEBUG 编译代码以获得详细的跟踪或不只获取结果。
我没有删除提示代码,但我自己的程序不会这样做。我可能还会让程序计算输入了多少值(使用动态内存分配为数据腾出空间)并简单地读取数据,直到它达到 EOF。为了测试,我使用了保存在文件中的三组随机生成的数字,以便可以重复测试。
我没有尝试修复原始的merge() 代码——我只是重写了它。我的问题概述了原始代码的一些问题。我相当确定问题中的代码没有充分注意哪些数字范围是有效的。此代码注释mergesort() 和merge() 的范围包括结束索引(因此main() 调用mergesort(a, 0, n - 1) 而不是问题中的mergesort(a, 0, n),例如)。
此合并代码首先将数据复制到b 数组中,然后从b 合并回a(或多或少类似于问题中的代码)——合并到b 中是可行的然后再从b复制到a。
#include <assert.h>
#include <stdio.h>
#define MAX 1000
#ifdef DEBUG
#define TRACE(...) printf(__VA_ARGS__)
#define DUMP(t, a, l, r) dump_array(t, a, l, r)
#else
#define TRACE(...) ((void)0)
#define DUMP(t, a, l, r) ((void)0)
#endif
/* Dump elements in range l <= i <= r */
static void dump_array(const char *tag, int a[], int l, int r)
{
assert(tag != 0 && a != 0 && l >= 0 && l <= r);
printf("%s[%d..%d]:", tag, l, r);
for (int i = l; i <= r; i++)
printf(" %d", a[i]);
putchar('\n');
}
/* Merge elements in ranges l <= i <= m and m+1 <= j <= r */
static void merge(int a[], int l, int m, int r)
{
assert(a != 0 && l >= 0 && l <= m && m <= r);
TRACE("-->> %s(): %d..%d..%d\n", __func__, l, m, r);
int b[r + 1];
for (int i = l; i <= r; i++)
b[i] = a[i];
DUMP("b", b, l, r);
int k = l;
int i = l;
int j = m + 1;
while (i <= m && j <= r)
{
if (b[i] <= b[j])
a[k++] = b[i++];
else
a[k++] = b[j++];
}
while (i <= m)
a[k++] = b[i++];
while (j <= r)
a[k++] = b[j++];
DUMP("a", a, l, r);
TRACE("<<-- %s(): %d..%d..%d\n", __func__, l, m, r);
}
/* Sort elements in range l <= i <= r */
static void mergesort(int a[], int l, int r)
{
assert(a != 0 && l >= 0 && l <= r);
if (r > l)
{
TRACE("-->> %s(): %d..%d\n", __func__, l, r);
DUMP("a", a, l, r);
int mid = (l + r) / 2;
mergesort(a, l, mid);
DUMP("a", a, l, mid);
mergesort(a, mid + 1, r);
DUMP("a", a, mid+1, r);
merge(a, l, mid, r);
DUMP("a", a, l, r);
TRACE("<<-- %s(): %d..%d\n", __func__, l, r);
}
}
int main(void)
{
int n;
int a[MAX];
printf("Enter the number of elements you want to create: ");
if (scanf("%d", &n) != 1 || n < 1 || n > MAX)
{
fprintf(stderr, "read error\n");
return 1;
}
for (int i = 0; i < n; i++)
{
printf("Enter your number %d: ", i);
if (scanf("%d", &a[i]) != 1)
{
fprintf(stderr, "read error\n");
return 1;
}
}
putchar('\n');
dump_array("Unsorted", a, 0, n - 1);
mergesort(a, 0, n - 1);
dump_array("Sorted", a, 0, n - 1);
return 0;
}
示例运行(-DDEBUG;包含 5 个元素的数据集 — 当然,打印出来是为了便于检查):
Enter the number of elements you want to create: Enter your number 0: Enter your number 1: Enter your number 2: Enter your number 3: Enter your number 4:
Unsorted[0..4]: 17 74 63 62 26
-->> mergesort(): 0..4
a[0..4]: 17 74 63 62 26
-->> mergesort(): 0..2
a[0..2]: 17 74 63
-->> mergesort(): 0..1
a[0..1]: 17 74
a[0..0]: 17
a[1..1]: 74
-->> merge(): 0..0..1
b[0..1]: 17 74
a[0..1]: 17 74
<<-- merge(): 0..0..1
a[0..1]: 17 74
<<-- mergesort(): 0..1
a[0..1]: 17 74
a[2..2]: 63
-->> merge(): 0..1..2
b[0..2]: 17 74 63
a[0..2]: 17 63 74
<<-- merge(): 0..1..2
a[0..2]: 17 63 74
<<-- mergesort(): 0..2
a[0..2]: 17 63 74
-->> mergesort(): 3..4
a[3..4]: 62 26
a[3..3]: 62
a[4..4]: 26
-->> merge(): 3..3..4
b[3..4]: 62 26
a[3..4]: 26 62
<<-- merge(): 3..3..4
a[3..4]: 26 62
<<-- mergesort(): 3..4
a[3..4]: 26 62
-->> merge(): 0..2..4
b[0..4]: 17 63 74 26 62
a[0..4]: 17 26 62 63 74
<<-- merge(): 0..2..4
a[0..4]: 17 26 62 63 74
<<-- mergesort(): 0..4
Sorted[0..4]: 17 26 62 63 74
示例运行(-UDEBUG 有 12 个元素 - 5 元素集使用该集中的前 5 个数字):
Enter the number of elements you want to create: Enter your number 0: Enter your number 1: Enter your number 2: Enter your number 3: Enter your number 4: Enter your number 5: Enter your number 6: Enter your number 7: Enter your number 8: Enter your number 9: Enter your number 10: Enter your number 11:
Unsorted[0..11]: 17 74 63 62 26 16 15 86 80 17 35 69
Sorted[0..11]: 15 16 17 17 26 35 62 63 69 74 80 86
示例运行(-UDEBUG 包含 30 个元素 - 完全是一组单独的随机数):
Enter the number of elements you want to create: Enter your number 0: Enter your number 1: Enter your number 2: Enter your number 3: Enter your number 4: Enter your number 5: Enter your number 6: Enter your number 7: Enter your number 8: Enter your number 9: Enter your number 10: Enter your number 11: Enter your number 12: Enter your number 13: Enter your number 14: Enter your number 15: Enter your number 16: Enter your number 17: Enter your number 18: Enter your number 19: Enter your number 20: Enter your number 21: Enter your number 22: Enter your number 23: Enter your number 24: Enter your number 25: Enter your number 26: Enter your number 27: Enter your number 28: Enter your number 29:
Unsorted[0..29]: 80 76 86 10 46 99 12 55 76 34 86 23 76 83 13 21 93 50 19 53 86 92 81 35 90 53 65 67 79 20
Sorted[0..29]: 10 12 13 19 20 21 23 34 35 46 50 53 53 55 65 67 76 76 76 79 80 81 83 86 86 86 90 92 93 99
我检查了 30 个元素的集合——获取未排序的数字列表,用sort -n 对它们进行排序,然后将该列表与排序后的输出进行比较。结果是相同的,这意味着排序的“排序顺序”和“守恒”属性是有效的。我观察了 5 和 12 组数据值的结果。