假设您有一系列城市名称。与每个城市相关的是一个州。在构建列表时,您希望按城市名称按字母顺序对其进行排序。列表完成后,您希望按状态对其进行排序。我的问题是,一旦按州名称排序,特定州的城市是否仍按字母顺序排列?或者是否需要使用每个州的城市名单?还是有另一种方法可以做到这一点吗?
答案 0 :(得分:4)
...一旦按州名称排序,特定州的城市是否仍然按字母顺序排列?
没有。 qsort()
不一定是stable。当元素彼此相等时,顺序可能会改变。
或者还有另一种方法吗?
避免从比较函数返回0。 @Weather Vane
int fcmp_by_state_then_by_city(const void *a, const void *b) {
const geo *ga = a; // assume array of geo
const geo *gb = b;
int cmp = strcmp(ga->state, gb->state);
if (cmp) return cmp;
return strcmp(ga->city, gb->city);
}
int fcmp_by_city_then_by_state(void *a, void *b) {
// like above with strcmp(ga->city, gb->city) first
}
一种简单的方法是将另一个成员添加到提供规范顺序的geo
类型 - 最终的打破平局 - 这可能是原始数组中元素的原始索引。另一种方法是创建一个指向数组元素的指针数组,并使用指向原始数组的指针进行排序,使用该第二级指针作为决胜局。
int fcmp_by_state_then_by_index(const void *a, const void *b) {
const geo *ga = a; // assume array of geo
const geo *gb = b;
int cmp = strcmp(ga->state, gb->state);
if (cmp) return cmp;
return (ga->index > gb->index) - (ga->index < gb->index)
}
使用地址a,b
作为最终的决胜局并不一定有效。 @chqrlie
如果两个元素相等,那么它们在生成的排序数组中的顺序是未指定的 C11§7.22.5.24
答案 1 :(得分:3)
不,qsort
不一定是stable sort。 *
听起来你需要定义一个词典比较器 - 比如你的比较器首先比较状态,然后只有状态相等才比较城市。
[7.20.5.2] 如果两个元素相等,那么它们在生成的排序数组中的顺序是未指定的。
答案 2 :(得分:0)
qsort
本身不需要稳定,并且在许多实现中都不是,尤其是在使用快速排序算法实现时。
这是解决此问题的简单方法:如果您的系统有mergesort()
,则此函数使用与qsort()
相同的API实现稳定排序。
否则,您可以借用合并排序的实现并使用它。