【问题标题】:qsort in C uses twice the amount of memoryC 中的 qsort 使用两倍的内存量
【发布时间】:2017-06-24 11:48:00
【问题描述】:

我有一个程序,我需要读取 RAM 中的数据字节,使用 qsort 对数据进行排序,然后将数据写回文件,问题是我只允许使用一定数量的内存来这样做。 这是我所做的事情的概要:

FILE *fp;
/* open file for reading up here , blah blah blah*/
...

int mb = 1024*1024;
int mem_size = 20*mb;
int total_cookies = mem_size/sizeof(Cookie);
Cookie *buffer = (Cookie *) calloc(total_cookies, sizeof(Cookie));

/* read bytes into buffer*/
 while ((result = fread(buffer, total_cookies , sizeof(Cookie), fp)) > 0) {
      qsort(buffer, total_cookies, sizeof(Cookie), compare);
      fwrite(....)
 }
 free(buffer);

我的问题是,当我针对 /usr/bin/time -v 运行我的程序并检查最大驻留集大小时,我使用了两倍的内存量,而问题又指向了 qsort 函数。

如何让 qsort 就地排序,而不使用额外的内存?

【问题讨论】:

  • 遗憾的是,C 标准对 qsort 的实现没有复杂性要求,只要结果正确,每个标准库实现者几乎可以做任何他们想做的事情。你唯一的选择是编写你自己的排序算法,你可以控制它。
  • 这太疯狂了,因为在我的作业中,我们不能超过一定的内存量,我们被告知要使用 qsort,因为其中一位助教说 qsort,排序到位。但是当我尝试解释我的结果时,我几乎得到了“那不应该发生的答案”。但我看不出我的实现哪里出了问题,而且我没有任何内存泄漏或任何东西......我绝对被难住了。
  • 你的助教被这个名字骗了。 This 是标准对 qsort 的评价。除了正确性之外,它没有任何要求。还有由全球开发人员公开维护的this source。试着用这些来说服你的助教他们应该调整他们的期望。如果 TA 不相信,请按要求完成作业。它要么传递 TA 的库实现,要么整个类将失败,他们将无法忽略。
  • @koikoi: qsort 可能确实 排序,但由于它(假设 qsort 实际上是作为快速排序实现的)是递归的,它可能会使用大量堆栈进行递归来电。也许您的数据几乎是排序的,或者几乎是反向的?
  • @koikoi 即使数据被反向排序,快速排序也会表现不佳。如果您知道您的实现中的qsort 实际上使用了快速排序(它不需要),您可能应该在调用qsort 之前对输入进行洗牌。快速排序在“随机”有序输入的“平均”情况下效果很好。

标签: c memory memory-management quicksort qsort


【解决方案1】:

由于规范中没有关于内存消耗或时间复杂度的要求,如果您对内存消耗有限制(至少如果您想要可移植性),您将需要使用另一个函数(可能自行实现)。

确实存在具有O(n log n) 复杂性和O(n log n) 内存消耗的算法(fx 快速排序)。可能有一些实现实际上使用这种算法来实现qsort,但你的可能不是这些。

还有其他体面的算法需要更多内存。例如,合并排序需要为最后一个合并步骤制作数据的副本(这与您的观察一致)。合并排序有它的优点(例如具有更好的最坏情况时间复杂度),这可能是实现选择该算法的原因。

实际上qsort 的实现在时间和内存方面都可能比这差很多。 qsort 就地排序的说法仅在结果最终以与输入相同的数组结束的情况下才是正确的,但在此之前它可能会将数据分散到各处。

【讨论】:

    猜你喜欢
    • 2011-08-15
    • 2013-07-21
    • 2012-12-28
    • 1970-01-01
    • 2012-04-17
    • 2017-10-20
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    相关资源
    最近更新 更多