我正在尝试创建常规的合并排序实现。我99%的人确定问题与我使用memcpy
的错误有关。
这是我合并2个数组的代码:
static inline void * merge(void *left, void *right,
size_t leftsz, size_t rightsz, size_t width, DArray_compare cmp)
{
size_t i = 0, k = 0, j = 0;
size_t sz = leftsz + rightsz;
void *res = NULL;
res = calloc(sz, width);
check_mem(res);
while (j < sz) {
if (i == leftsz) {
memcpy(res + j*width, right + k*width, width);
++i;
} else if (k == rightsz) {
memcpy(res + j*width, left + i*width, width);
++k;
} else if (cmp(left + i*width, right + k*width) < 0) {
debug("Here");
memcpy(res + j*width, left + i*width, width);
++i;
} else {
memcpy(res + j*width, right + k*width, width);
++k;
}
debug("------PRINTING RES------\n");
for (int t = 0; t < j; t++) {
debug("%s\n", * (char **) res + t);
}
debug("----FINISHED PRINTING RES----\n");
++j;
}
return res;
error:
return NULL;
}
其中sz
是最终合并数组的大小,leftsz
是左半部分的大小,rightsz
是右半部分的大小。 width
是指每个元素的大小。
每当我在数组{ "asdfasfd", "werwar", "13234", "asdfasfd", "oioj" }
上运行此命令时,它都表示该数组未正确排序。
这是主要的合并排序代码:
int merge_sort(void *arr, size_t size,
size_t width, DArray_compare cmp)
{
if (size <= 1)
return 0;
size_t lsize = size / 2, rsize = size - (size / 2);
void *left = NULL, *right = NULL, *res = NULL;
left = calloc(lsize, width);
check_mem(left);
right = calloc(rsize, width);
check_mem(right);
memcpy(left, arr, lsize*width);
memcpy(right, arr + lsize*width, rsize*width);
debug("Looping over right array.");
for (int i = lsize; i < size; i++) {
debug("%s", * ((char **) right + (i-lsize)));
}
merge_sort(left, lsize, width, cmp);
merge_sort(right, rsize, width, cmp);
res = merge(left, right, lsize, rsize, width, cmp);
check_mem(res);
free(left);
free(right);
memcpy(arr, res, size*width);
free(res);
return 0;
error:
if (left) free(left);
if (right) free(right);
if (res) free(res);
return -1;
}
同样,我肯定由于memcpy
,我的实现工作搞砸了。但是,我不确定我是如何使用它的。
我在数组merge_sort
上运行了{ "asdfasfd", "werwar", "13234", "asdfasfd", "oioj" }
函数,就像这样:
int rc = merge_sort(words->contents, words->end,
sizeof(void *), (DArray_compare) testcmp);
...
words->contents
是void **
数组,而words->end
是数组的大小。 words
本身是代表动态数组的结构。我知道该阵列是正确构建的,所以我认为这不是问题的根源。
如有必要,随时询问我更多信息。
谢谢。
编辑:
这是一个例子:
int main(int argc, char *argv[])
{
char *words[] = { "asdfasfd",
"werwar", "13234", "asdfasfd", "oioj"};
merge_sort((void **)&words, 5,
sizeof(void *), testcmp);
for (int i = 0; i < 4; i++) {
if (strcmp(words[i], words[i+1]) > 0) {
printf("NOT SORTED\n");
return 1;
}
}
return 0;
}
答案 0 :(得分:0)
好吧,看来我对合并排序失败的原因是错误的。
正如伊恩·雅培(Ian Abbott)所说,if (i == leftsz)
应该是if (i >= leftsz)
,而(k == rightsz)
应该也是如此。这样可以防止将数据复制到数组末尾。非常感谢!
编辑:
此外,我在j
循环之前添加了以下内容:
for (int t = 0; t < sz; t++) {
char *ptr = res + t*width;
ptr = calloc(1, width);
check_mem(ptr);
}
没有此部分代码,以上操作将无效。