【问题标题】:Stable Merge sort C稳定归并排序 C
【发布时间】:2012-01-03 04:16:17
【问题描述】:

我正在编写一个简单的合并排序函数来根据给定的 compar 函数进行排序:

void merge(int left, int mid, int right, int(*compar)(const void *, const void *))
{
  // sublist sizes
  int left_size = mid - left + 1;
  int right_size = right - mid;

  // counts
  int i, j, k;

  // create left and right arrays
  B *left_list = (B*) malloc(left_size*sizeof(B));
  B *right_list = (B*) malloc(right_size*sizeof(B));

  // copy sublists, could be done with memcpy()?
  for (i = 0; i < left_size; i++)
    left_list[i] = list[left + i];

  for (j = 0; j < right_size; j++)
    right_list[j] = list[mid + j + 1];

  // reset counts
  i = 0; j = 0;

  for (k = left; k <= right; k++)
  {
    if (j == right_size)
      list[k] = left_list[i++];
    else if (i == left_size)
      list[k] = right_list[j++];
    // here we call the given comparision function
    else if (compar(&left_list[i], &right_list[j]) < 0)
      list[k] = left_list[i++];
    else
      list[k] = right_list[j++];
  }
}

void sort(int left, int right, int(*compar)(const void *, const void *))
{
  if (left < right)
  {
    // find the pivot point
    int mid = (left + right) / 2;

    // recursive step
    sort(left, mid, compar);
    sort(mid + 1, right, compar);

    // merge resulting sublists
    merge(left, mid, right, compar);
  }
}

然后我使用不同的比较函数在同一个 list 数组上多次调用它。我发现第一次调用的排序是稳定的,但之后我看到元素被交换了,即使它们是相等的。

谁能提出这种行为的原因?

【问题讨论】:

  • 什么是list?为什么有malloc 而没有free
  • 与您的问题无关,但您可能希望释放在 merge 函数中分配的内存。
  • compar(&amp;left_list[i], &amp;right_list[j]) &lt;= 0(将比较更改为
  • 顺便问一下B是什么类型的?
  • 我需要添加 free() 是的,这可能是多次重新调用函数时出现奇怪行为的原因吗?

标签: c sorting mergesort


【解决方案1】:

我不确定这是否会这样做,但请尝试更改此行:

compar(&left_list[i], &right_list[j]) < 0

到这里:

compar(&left_list[i], &right_list[j]) <= 0

这将使得如果它们已经相等,它会执行第一个动作,这将(​​希望)保持稳定性而不是移动物体。

这只是猜测。

【讨论】:

  • 此更改似乎相反,即使它们相等也进行交换。如果我按预期运行算法一次,就在我在更新的列表上再次运行它时[] 好像不太稳定。
  • 很抱歉,只是瞎猜。尝试查看 C 中现有的合并排序并将代码与您拥有的代码进行比较?或者也许可以逐步浏览维基百科上的伪代码? en.wikipedia.org/wiki/Merge_sort
  • 我刚刚意识到打印输出数据的功能是倒序排列,所以这实际上是正确的解决方案! - 手掌 -> 脸!谢谢你..
  • 哈哈今天是星期一:P '
【解决方案2】:

我认为你的尺码有误

int left_size = mid - left;

而且,正如 arasmussen 所指出的,您需要优先考虑左侧列表以保持稳定性

compar(&left_list[i], &right_list[j]) <= 0

除了所有这些之外,您不会在 malloc 后调用 free 帮助列表。这不会使算法返回不正确的结果,但会导致程序的内存使用在您每次调用排序函数时不可逆转地增长。

【讨论】:

    猜你喜欢
    • 2017-12-16
    • 1970-01-01
    • 1970-01-01
    • 2014-04-08
    • 2012-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多