如何使用qsort保持相等的顺序不变

时间:2015-07-20 13:50:50

标签: c sorting qsort stable-sort

直接从qsort手册中说:

  

如果两个成员相等,则它们在排序数组中的顺序是未定义的。

但是,我希望qsort在相等的情况下保持顺序不变。也就是说,如果它们具有用于排序的相同值,则保留原始数组中两个元素的排序。

我不确定如何使用qsort执行此操作。我宁愿不使用替代排序库/自己滚动。

由于

-

编辑:现在我知道稳定和不稳定排序之间的区别我发现这是重复的。

4 个答案:

答案 0 :(得分:3)

您实际上是在询问如何在不稳定的排序之上实现稳定排序。

您无能为力:您只能控制比较功能,因此您必须对此进行处理。

一种可能性是将第二个键ID附加到数组中与该元素的原始索引相对应的每个元素。然后,如果两个元素比较相等,只需根据原始索引返回相应的顺序。

答案 1 :(得分:3)

正如GNU libc manual所解释的那样,

  

使用qsort执行稳定排序的唯一方法是首先使用某种单调计数器来扩充对象。

因此,除非您可以修改比较函数以便可以区分当前认为“相等”的对象,否则在排序之前必须使用索引显式地注释对象,并在完成后删除索引。你可以使用像

这样的东西
struct indexed {
    void *obj;
    int index;
}

答案 2 :(得分:2)

qsort告诉你的是他的算法不允许它保证两个等于成员的排序顺序。

您可以做的是实施/使用其他算法,或强迫他们按照原来的方式进行排序:

  • 如果您的比较函数应返回相等,请查看它们最初的排序方式,并以相同的方式对它们进行排序。

答案 3 :(得分:1)

qsort代表“Quick Sort”,这是一种快速但不稳定的排序算法。假设您按升序排序。在这种情况下,如果排序算法不会交换具有相同键的元素,则称为 stable 。如果它可以用相同的键交换元素,那么不稳定

您的问题有不同的解决方案;我会在这里建议其中两个。

解决方案1 ​​

您可以在维基百科中找到一些有趣的想法 stability of sorting algorithms,包括在实际需要稳定算法时使用不稳定算法的方法:扩展排序键:例如,如果使用整数值进行排序。

假设您正在排序整数数组。而不是那样,你创建一个包含两个元素的结构:第一个(KEY)是你的整数。第二个(AUX_KEY)是唯一索引。在排序之前,您将线性设置AUX_KEY以反映原始顺序。排序时,传递给qsort一个将使用KEY排序的函数,但如果两个键相等,则会恢复使用AUX_KEY

解决方案2

使用像merge sort这样的稳定​​算法,而不是使用Quicksort,你可能在编程环境中使用了这个算法(例如,这里是FreeBSD manpage for mergesort;在其他编程环境中也可以使用相同的名字 - 请检查)或者,如果您不需要速度太快,请使用insertion sort(您可以自己编码 - 仅在伪代码中需要几行)。插入排序采用二次时间复杂度(时间与n ^ 2成比例),而mergesort和quicksort的时间复杂度为O(n log(n))。