我想对int
类型列表进行排序。但是当合并功能中的参数是double
列表时,它可以工作!但不在int
列表中时...
这里是排序功能。参数是int
指针。
如果将int
列表更改为double
列表可以正常工作。
ex)int *a
-> double *a
ex)int *l, *r1
-> double *l, *r1
ex)l = (int *)calloc(n1+1,sizeof(int)), r1 = (int *)calloc(n2+1,sizeof(int))
-> l = (double *)calloc(n1+1,sizeof(double)) r1 = (double *)calloc(n2+1,sizeof(double))
void merge(int *a, int p, int q, int r) {
int n1 = q - p + 1;
int n2 = r - q;
int *l, *r1;
int i, j, k;
l = (int *)calloc(n1 + 1, sizeof(int));
r1 = (int *)calloc(n2 + 1, sizeof(int));
for (i = 0; i < n1;i++)
l[i] = a[p + i];
for (j = 0; j < n2; j++)
r1[j] = a[q + 1 + j];
l[n1] = 10000;
r1[n2] = 10000;
i = 0;
j = 0;
for (k = p; k <= r; k++) {
if (l[i] <= r1[j]) {
a[k] = l[i];
++i;
} else {
a[k] = r1[j];
++j;
}
}
return;
}
这是递归函数。直到列表的长度为1
ex)int *a -> double *a
void merge_sort(int *a, int p, int r) {
if (p < r) {
int q = (p + r) / 2;
merge_sort(a, p, q);
merge_sort(a, q + 1, r);
merge(a, p, q, r);
}
}
创建一个长度为10
的列表,并将其放入mergesort
函数中。然后打印列表。
int main(int argc, char *argv[]) {
int i, *a[10];
for (i = 0; i < 10; i++) {
a[i] = rand() % 10 + 1;
}
merge_sort(a, 0, 10);
for (i = 0; i < 10; i++) {
printf("%d ", a[i]);
}
return 0;
}
结果是
0 0 0 2 5 10 9 9 3 5
答案 0 :(得分:0)
您的代码中存在多个问题:
main
函数中进行更改),还必须更改printf
格式。提高警告级别(gcc -Wall -Wextra -Werror
)可以防止愚蠢的错误。a
中main
的定义不正确,应该为int a[10];
,而不是指向int
的指针数组。mergesort()
中的main
:merge_sort(a, 0, 10);
,这意味着应排除合并排序中的r
。那么merge_sort(a, q + 1, r);
中的递归调用mergesort
是不正确的,因为q
应该排除在merge_sort(a, p, q);
中,但应包括在下半部分。请改用merge_sort(a, q, r);
。int q = (p + r) / 2;
计算段的中间位置。您可能对大型数组有未定义的行为,因为q + r
可能溢出类型int
的范围。这是一个经典的错误,在有人将代码用于大型数组之前,几十年来可能不会被注意到。使用int q = p + (r - p) / 2;
避免出现这种情况。merge
中的算法不正确:您假设数组中的所有值均为< 10000
,这可能是无效的假设。该代码应处理所有可能的值。您应该测试索引变量以检测子数组的末尾并专门处理其他数组的剩余值。merge
中分配的数组,从而导致内存泄漏。typedef
。这是改进版:
#include <stdio.h>
#ifdef USE_DOUBLE
typedef double sorttype;
#else
typedef int sorttype;
#endif
void merge(sorttype *a, int p, int q, int r) {
// merge subarrays a[p...q] and a[q...r]
// upper bounds q and r are excluded
int n1 = q - p;
int n2 = r - q;
sorttype *a1, *a2;
int i, j, k;
a1 = malloc(n1 * sizeof(*a1));
a2 = malloc(n2 * sizeof(*a2));
for (i = 0; i < n1; i++)
a1[i] = a[p + i];
for (j = 0; j < n2; j++)
a2[j] = a[q + j];
i = 0;
j = 0;
for (k = p; k < r; k++) {
if (i < n1 && (j >= n2 || a1[i] <= a2[j])) {
a[k] = a1[i];
++i;
} else {
a[k] = a2[j];
++j;
}
}
free(a1);
free(a2);
}
void merge_sort(sorttype *s, int p, int r) {
if (r - p > 1) {
int q = p + (r - p) / 2;
merge_sort(s, p, q);
merge_sort(s, q, r);
merge(s, p, q, r);
}
}
int main(int argc, char *argv[]) {
sorttype a[10];
int i;
for (i = 0; i < 10; i++) {
a[i] = 1 + rand() % 10;
}
merge_sort(a, 0, 10);
for (i = 0; i < 10; i++) {
#ifdef USE_DOUBLE
printf("%g ", a[i]);
#else
printf("%d ", a[i]);
#endif
}
printf("\n");
return 0;
}
int
的输出:
1 3 4 4 5 8 9 9 10 10
double
的输出:
1 3 4 4 5 8 9 9 10 10
请注意,尽管重新编译并重新运行了程序,但随机数却是相同的...您应使用srand(clock())
尝试获得不同的伪随机序列。
还要注意,不需要分配a2
来复制右边的子数组,因为合并操作不会覆盖右边一半尚未复制的元素。
此外,您应该测试分配失败并报告。
这是merge
的改进版本:
void merge(sorttype *a, int p, int q, int r) {
// merge subarrays a[p...q] and a[q...r]
// upper bounds q and r are excluded
int n1 = q - p;
int n2 = r - q;
sorttype *a1;
int i, j, k;
a1 = malloc(n1 * sizeof(*a1));
if (a1 == NULL) {
fprintf(stderr, "memory allocation failure\n");
exit(1);
}
for (i = 0; i < n1; i++)
a1[i] = a[p + i];
i = 0;
j = 0;
for (k = p; i < n1 && k < r; k++) {
if (j >= n2 || a1[i] <= a[q + j]) {
a[k] = a1[i];
++i;
} else {
a[k] = a[q + j];
++j;
}
}
free(a1);
}