我在C中的Mergesort程序中找不到错误。 它总是显示分段错误。
这是Mergesort的代码:
我认为问题可能在这里:
void merge(int *a, int i, int mid, int n) {
int l, m, k, b[10];
l = i;
m = mid + 1;
k = 0;
while (l <= mid && m <= n) {
if (a[l] > a[m])
b[k++] = a[l++];
if (a[m] > a[l])
b[k++] = a[m++];
}
while (l <= mid)
b[k++] = a[l++];
while (m <= n)
b[k++] = a[m++];
for (k = 0; k < n; k++)
a[i++] = b[k];
return ;
}
答案 0 :(得分:0)
接近你的功能的结尾(在其他地方..):
for(k=0;k<n;k++) // k = [0 -> n)
a[i++]=b[k]; // but b is declared as int b[10], this is surely not right.
上述循环意味着您希望b
在某个时刻保留n
个元素。为什么'b'尺寸不合适?
答案 1 :(得分:0)
您的代码中存在多个问题:
mid
参数似乎是左半部分中最后一个元素的索引,而n
是右半部分中最后一个元素的索引。这与C中的常见做法不一致,i
是左半部分的索引,mid
应该是右半部分的第一个元素的索引,n
应该是索引到了右半边以外的第一个元素。这样,通过从索引中减去最后一个元素之外的初始索引,可以很容易地计算数组长度。
b
在本地分配为大小为10
的数组。如果要合并的块的大小大于10,则这是不正确的。您可以使用(n - i)
分配malloc()
个元素的数组,或者如果大小,则定义本地数组int b[n - i];
要排序的数组不是太大(对于现代64位环境,不到100万个条目)。
l
对于局部变量的名称来说是一个糟糕的选择:它在图形上太接近1
,从而产生了潜在的错误和混淆。
主合并循环中的测试既冗余又不完整:你不处理左半边的元素与右半边的元素相等的情况。
最后一个循环,将合并后的数据复制回源数组是有缺陷的:它应该是:
for (k = 0; k < n - i; k++)
a[i++] = b[k];
以下是适度小型数组的更正版本:
void merge(int *a, int start, int mid, int end) {
int i, j, k, b[end - start];
i = start;
j = mid;
k = 0;
while (i < mid && j < n) {
if (a[i] <= a[j])
b[k++] = a[i++];
else
b[k++] = a[j++];
}
while (i < mid) {
b[k++] = a[i++];
}
while (j < n) {
b[k++] = a[j++];
}
for (i = start, k = 0; i < end; i++, k++) {
a[i] = b[k];
}
}
void mersort(int *a, int length) {
if (length > 1)
int mid = length / 2;
mergesort(a, mid);
mergesort(a + mid, length - mid);
merge(a, 0, mid, length);
}
}