稳定排序和不稳定排序的区别不只是「相同元素会不会换位置」。这篇用相同 key 的例子证明稳定性,用分配器计数看内存,用 100 万个元素测速度,再看 key 函数的调用次数和 f64 排序的出路。
编译:成功
运行(退出码 0):
200 个元素、3 种 key:sort_by_key 保持了相同 key 的原顺序: true sort_unstable_by_key 保持了: false
sort_unstable 打乱的一个例子:相邻两个 key 相同的元素 (0, 113) 排在 (0, 6) 前面(原始序号反了)
两种排序的 key 序列相同: true 编译:成功
运行(退出码 0):
n= 10: sort 分配 0 次 0 字节 sort_unstable 分配 0 次 0 字节
n= 20: sort 分配 0 次 0 字节 sort_unstable 分配 0 次 0 字节
n= 100: sort 分配 0 次 0 字节 sort_unstable 分配 0 次 0 字节
第一个让 sort 发生堆分配的元素个数(u64,在 1..=5000 里扫描): Some(513);sort_unstable 在 1..=5000 里的第一次分配: None
n= 10000: sort 分配 1 次 80000 字节 sort_unstable 分配 0 次 0 字节 编译:成功
运行(退出码 0):
随机 sort 14.313 ms sort_unstable 11.198 ms
已有序 sort 0.296 ms sort_unstable 0.295 ms
逆序 sort 0.435 ms sort_unstable 0.436 ms
大量重复 sort 2.281 ms sort_unstable 2.054 ms耗时是本机 release 实测,元素是 u64;更大的元素或昂贵的比较函数会改变结论。
编译:成功
运行(退出码 0):
1000 个元素:sort_by_key 的 key 函数被调用 20898 次;sort_by_cached_key 调用 1000 次;结果相同: true 源码:
1 | fn main() { let mut v = vec![2.5, 1.0]; v.sort(); }
编译:失败
error[E0277]: the trait bound `{float}: Ord` is not satisfied
--> <实验目录>/src/u69e.rs:1:43
|
1 | fn main() { let mut v = vec![2.5, 1.0]; v.sort(); }
| ^^^^ the trait `Ord` is not implemented for `{float}`
|
= help: the following other types implement trait `Ord`:
i128
i16
i32
i64
i8
isize
u128
u16
and 4 others
note: required by a bound in `slice::<impl [T]>::sort`
--> <rust 标准库源码>/library/alloc/src/slice.rs:133:12
|
131 | pub fn sort(&mut self)
| ---- required by a bound in this associated function
132 | where
133 | T: Ord,
| ^^^ required by this bound in `slice::<impl [T]>::sort`
…(共 28 行)
编译:成功
运行(退出码 0):
total_cmp: [-1.0, -0.0, 0.0, 1.0, 2.5, NaN]
partial_cmp.unwrap(): [-1.0, 1.0, 2.5]
total_cmp 把 -0.0 排在 0.0 前面,NaN 排在最后(正 NaN)f64 没有 Ord 的原因与 NaN 有关,这里只验证了编译错误与 total_cmp 的输出。