【发布时间】:2018-02-21 07:30:06
【问题描述】:
我需要使用 qsort 对数组进行稳定排序。为了保证结果稳定,我在比较函数中增加了一个条件:
int compare(const void *p1, const void *p2)
{
if(*(const Data*)p1 < *(const Data*)p2)
return -1;
if(*(const Data*)p2 < *(const Data*)p1)
return 1;
else
return p1<p2 ? -1 : 1;
}
如果 qsort 从不调用 compare(p,p),这将起作用。否则我需要使用更复杂的条件。问题是,qsort 是否曾经使用重复指针调用 compare(),还是总是比较不同的指针?
更新:
我用 Ideone C++ 编译器检查了这个:https://ideone.com/l026kM
对于 cmets 中的小示例 { 8, 8, 1, 1 },提供的 qsort() 实现不会更改指针的顺序,也不会为同一元素调用 compare。这似乎是合理的,因为每次反向交换都会影响性能,因为它需要稍后再交换回来。我将使用随机生成的数组和不同的编译器对此进行测试。
更新:
在 Ideone 上针对 100000 个随机数组进行测试,其中重复键的份额至少为 80%。结果是 100% 稳定的排序数组。这是链接:https://ideone.com/KOYbgJ
VC++Express 2008 编译器失败 稳定排序,因为指针的顺序改变了。这基本上说明了 VC++ 实现与 GCC 实现的不同之处在于它不保持指针顺序。
【问题讨论】:
-
听说过
std::stable_sort吗? -
你为什么还要在所谓的 C++ 程序中使用 C 库的 qsort?
-
顺便说一句,我认为这是一个 XY 问题。比较器的属性不影响排序算法的稳定性保证。
-
@bkxp 学习一些关于排序的理论。如果元素的排序键取决于它们的位置,则无法排序。
-
@bkxp 当然可以。它对性能意味着什么?没有。原始复制和赋值都可能导致完全相同的机器代码。