通常在C中实现合并排序

时间:2019-06-05 16:33:53

标签: c sorting mergesort

我正在尝试创建常规的合并排序实现。我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->contentsvoid **数组,而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;
}

1 个答案:

答案 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);
}

没有此部分代码,以上操作将无效。