排序评价维度
- 时间复杂度
- 是否为原地排序(空间复杂度)
- 是否稳定排序(是否破坏等值元素的原有先后顺序)
- 总览
冒泡排序思路
- 原则:大数沉底
- 具体:
- 从第一个位置往后,相邻元素对比,大数交换
- 一轮下来保证最后一个元素为本次排序最大数
- 重复以上操作,依次得到本次排序次大数、第三大数…
- 以上实现升序排列
插入排序思路
- 原则:依次插入
- 具体:
- 默认第一个元素为已排序列表
- 从第二个元素开始,遍历已排序列表获取插入位置,插入已排序列表
- 补充:遍历方向从尾部向前,发现比待插入元素更小元素,则插入位置为该元素之后,并退出当前遍历
选择排序思路
快排思路
quick_sort(p...r) = quick_sort(p...q-1) + quick_sort(q+1...r)
quick_sort终止条件:p >= r
quick_sort($array, $size) {
quick_sort_c($array, 0, $size-1);
}
quick_sort_c(&$array, $p, $r) {
if ($p >= $r) return;
$q = partition($array, $p, $r);
quick_sort($array, $p, $q-1);
quick_sort($array, $q+1, $r);
}
归并排序思路
merge_sort(p...r) = merge( merge_sort(p..q) + merge_sort(q+1...r) )
merge_sort终止条件:p >= r
merge_sort($array, $size) {
return merge_sort_c($array, 0, $size-1);
}
merge_sort_c($array, $p, $r) {
if ($p >= $r) return [];
$q = intval(($p+$r)/2);
$left = merge_sort_c($array, $p, $q);
$right = merge_sort_c($array, $q+1, $r);
return merge($left, $right);
}
桶排序思路
- 过程:
- 设定每个桶是一个排序范围
- 扫描全部元素,把元素归置到不同的桶中(范围内)
- 每个桶内部自行排序
- 最后把各桶元素依次串联得到最终结果
- 适用场景: 数据量大,无法在内存中实现排序,例如:全省高考总分排序等
计数排序思路
- 评价:计数排序是桶排序特殊情况,一个桶从一个范围变成了一个数,详情举例说明
- 适用场景:数据范围不大,非负数情况
- 举例:给8个考生成绩排序,成绩分数范围是0~10
$source = [3,9,0,4,5,2,7,1];
function count_sort($source, $size) {
if ($size <= 1) return $source;
$max = $source[0];
for ($i=1; $i<$size; ++$i) {
if ($max < $source[$i]) $max = $source[$i];
}
$range = [];
for ($i=0; $i<=$max; ++$i) {
$range[$i] = 0;
}
for ($i=0; $i<$size; ++$i) {
++$range[$source[$i]];
}
for ($i=1; $i<=$max; ++$i) {
$range[$i] += $range[$i-1];
}
$rs = $source;
for ($i=0; $i<$size; ++$i) {
$elem = $source[$i];
$rs[$range[$elem]-1] = $elem;
$range[$elem]--;
}
return $rs;
基数排序思路
- 适用场景:手机号排序、词典排序
- 思路:
- 针对位依次排序,以手机号排序举例
- 所有手机号先按照倒数第一个数字排序,使用桶排序或计数排序(数字范围是0~9),复杂度O(n)
- 在保证稳定排序前提下(数值相同手机号原有先后顺序不变动),所有手机号继续按照倒数第二个数字排序…
- 重复以上操作11次完成排序,排序结果类似如下:
13781234567
13781311111
13800000000
....
其他
- 以上是常见的排序算法介绍,排序是算法入门的基础
- 对运用层来说,编程语言已提供性能高效稳定的排序接口,开发者可直接调用
- 稳定高效的工业级排序算法不止使用一种排序方法,逻辑更复杂考虑更全面,有需要可以自行阅读源码