很抱歉在这里烦人,但我的合并排序代码存在问题。以前我可以编写双向合并排序代码,当我尝试将我的合并排序调整为3向合并排序时,我的编译器给了我:9154 segmentation fault(core dumped)
。你能帮我解决这个问题吗?有我的代码:
#include <stdio.h>
void merge(int v[], int p, int q, int r) {
int i, j, k, b[10];
for (i = p; i <= q; i++) {
b[i] = v[i];
}
for (j = q + 1; j <= r; j++) {
b[r + q + 1 - j] = v[j];
}
i = p;
j = r;
for (k = p; k <= r; k++) {
if (b[i] <= b[j]) {
v[k] = b[i];
i++;
} else {
v[k] = b[j];
j--;
}
}
}
void mersort(int v[], int p, int r) { //2-way mergesort that works
int q;
if (p < r) {
q = (p + r) / 2;
mersort(v, p, q);
mersort(v, q + 1, r);
merge(v, p, q, r);
}
}
void mersort3(int v[], int p, int r) {//not working
int q, s;
if (r > p) {
q = p + (p + r) / 3;
s = p + 2 * ((p + r) / 3) + 1;
mersort3(v, p, q);
mersort3(v, q, s);
mersort3(v, s, r);
merge(v, p, q, s);
merge(v, p, s, r);
}
}
答案 0 :(得分:2)
您的主要问题是由于索引计算不当导致的超出范围索引,以及出于同样原因的潜在无限递归。
你过度复杂化了。 C的一个很好的优点是pointer arithmetic,这使得序列分区和遍历这样的事情变得非常简单。作为奖励,您还可以删除一个函数参数,因为它的唯一原因是基本调整,它由指针算法处理。
例如,一个简单的基于VLA的合并算法(显然,不要用大序列调用它)
/* a simple little VLA-based merge. don't invoke with huge arrays */
void merge(int v[], size_t mid, size_t len)
{
if (len < 2)
return;
size_t i=0, j=mid, k=0;
int tmp[len];
while (i < mid && j < len)
tmp[k++] = (v[i] < v[j]) ? v[i++] : v[j++];
memcpy(tmp+k, v+i, (mid-i) * sizeof *v);
memcpy(v, tmp, (k + (mid-i)) * sizeof *v);
}
嗯,不是指针算术的一个很好的展示,但那里有一些。它真正闪耀的地方是分区算法。例如,一个简单的合并排序:
void mersort(int v[], size_t len)
{
if (len < 2)
return;
size_t mid = len/2;
mersort(v, mid);
mersort(v+mid, len-mid); // see here.
merge(v, mid, len);
}
将其扩展为三向分区方案:
void mersort3(int v[], size_t len)
{
if (len < 3)
{
mersort(v, len);
return;
}
size_t m1 = len/3;
size_t m2 = (2 * len)/3;
mersort3(v, m1);
mersort3(v+m1, m2-m1); // see here
mersort3(v+m2, len-m2); // and here
merge(v, m1, m2);
merge(v, m2, len);
}
使用保证异常分区大小的示例调用如下(序列长度为29个元素)
int main()
{
srand((unsigned)time(NULL));
const size_t N = 29;
size_t i,j;
int ar[N], n=0;
// build a sequence from 1..29
for (i=0; i<N; ++i)
ar[i] = ++n;
// shuffle the sequence
for (i=0; i<3; ++i)
{
for (j=0; j<N; ++j)
{
n = rand() % N;
int tmp = ar[n];
ar[n] = ar[j];
ar[j] = tmp;
}
}
// show the shuffled sequence
for (i=0; i<N; ++i)
printf("%d ", ar[i]);
fputc('\n', stdout);
// sort it
mersort3(ar, N);
// show it again
for (i=0; i<N; ++i)
printf("%d ", ar[i]);
fputc('\n', stdout);
return EXIT_SUCCESS;
}
输出(改组后的序列不同)
21 8 11 27 18 9 17 28 20 14 15 1 29 6 19 22 7 2 16 23 5 12 4 3 10 26 13 25 24
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29