【发布时间】:2020-01-11 02:33:31
【问题描述】:
我正在尝试实现这个合并排序函数来对 c 中的结构数组进行排序。当我调用该函数时,我的程序提前退出,我认为这是因为我正在排序的数组是 row_t* 类型并且需要是 row_t**,我不确定如何正确地分配我的数据以实现这一点。
//I have copied relevant bits of my code below
//this is the struct i am trying to sort by the value S
typedef struct
{
double rho, u, v, x, y, flux_u, flux_v, S;
} row_t;
//This is where i allocate the array i want to sort
row_t* linear_row_arr = (row_t*)malloc(sizeof(row_t)*100);
//this is where i try to call the function,
//linear_row_arr is an array of row_t, with 100 elements
merge_sort((void**)linear_row_arr, 99, row_array_s_comp);
//This is the function i am trying to call.
void merge(void** array, int n, int mid, int cmp(const void*, const void*))
{
// (0) need extra space for merging
void** tmp = malloc(n * sizeof(void*));
void** left = array;
void** right = array + mid;
int i = 0;
int j = 0;
int left_size = mid;
int right_size = n - mid;
// (1) perform the merge
for (int k = 0; k < n; k++) {
if (j == right_size)
tmp[k] = left[i++];
else if (i == left_size)
tmp[k] = right[j++];
else if (cmp(left[i], right[j]) < 1)
tmp[k] = left[i++];
else
tmp[k] = right[j++];
}
// (2) copy the merged array
for (int i = 0; i < n; i++) {
array[i] = tmp[i];
}
// (3) clean up
free(tmp);
}
void merge_sort(void** array, int n, int cmp(const void*, const void*))
{
if (n > 1) {
int mid = n / 2;
merge_sort(array, mid, cmp);
merge_sort(array + mid, n - mid, cmp);
merge(array, n, mid, cmp);
}
}
int row_array_s_comp(const void* a, const void* b)
{
row_t* ra = (row_t*)a;
row_t* rb = (row_t*)b;
// with int data we can just subtract to get the right behaviour
return ra->S - rb->S;
}
当我运行此代码时,代码会提前退出且没有错误消息。
编辑:
我尝试使用@Ian Abbott 的解决方案,但它在我的比较函数中产生了段错误。难道是我使用 malloc 而不是 calloc 来为我的数据分配内存?
// This is my function call
//100 elements of row_t*
merge_sort(linear_row_arr, 100, sizeof(row_t*), row_array_s_comp);
编辑 2: 谢谢伊恩,我已经修复了我的错误,现在有一个方便的合并排序功能可供我使用。我对您的答案投了赞成票,但它说它将公开显示,因为我的代表少于 15 个。如果有人需要,这里是我使用的最终比较函数是
int row_array_s_comp(const void* a, const void* b)
{
row_t* ra = (row_t*)a;
row_t* rb = (row_t*)b;
// with double data we can just subtract to get the right behaviour
return (ra->S > rb->S) - (ra->S < ra->S);
}
and i called the function with
merge_sort(linear_row_arr, 100, sizeof(row_t), row_array_s_comp);
如果有人觉得这个有用,请随时支持@Ians Abotts 的回答,因为它是正确的,但我不能。 再次感谢您的宝贵时间!
【问题讨论】:
-
您将指向
row_t数组的第一个元素的指针传递给需要指向void *数组的第一个元素的指针。难怪它不起作用。我建议将merge_sort参数更改为类似于标准库qsort函数,将元素大小传递给函数并将要排序的元素视为字节数组(使用memcpy复制它们)。跨度> -
感谢您的回复。你能指出我从哪里开始吗?我没有编写此合并排序,并且对如何实现您上面所说的没有信心。
-
顺便说一下,您的
row_array_s_comp函数没有正确按S值排序。它减去double并将结果隐式转换为int。如果绝对差值小于 1,则函数将返回 0。我建议使用return (ra->S > rb->S) - (ra->S < ra->S);。这将返回 -1、0 或 1。 -
我担心您将比较函数的返回类型更改为
double,因为这与我的merge_sort函数中的比较函数指针不匹配。比较函数返回int更为常规。 -
啊,我返回了实际差异,然后决定在比较函数之外哪个更大,我现在将我的代码更新为约定,然后更新帖子。