背景
本来想一口吃个大胖子。直接一篇文章搞定所有常见排序,发现水平不够,篇幅超过控制。故而决定一篇一篇先单独写,之后再发排序算法的总和篇(社畜像现实低头orz.)
选择排序 (Selection Sort)
本文要讲的排序算法是排序算法中最基本算法之一的选择排序(Selection Sort) 。
什么是选择排序?
选择排序的命名“选择”已经很好的解释了其算法的基本思想。试想学生时代体育课叫一堆小朋友从矮到高排序是怎么做的?大家总是找到最高的那个或者最矮的那个让TA到一边去,接着在剩余的小朋友里面再挑出最高或最矮的,让TA到一边排好序的小朋友堆里,如此往复,就能完成小朋友的排序了,那么这个其实就是咱们的选择排序了。
选择排序,每一次在未排序的元素里 “选择” 出最大(或最小)的元素,让其加到有序元素里。每一次能够令未排序元素 - 1 ,有序元素 + 1。N次之后就能完成所有元素的排序。
选择排序的空间时间复杂度
时间复杂度: O(n²),一共n轮,每一轮需要遍历剩余所有的元素,所以复杂度为n²。
空间复杂度: O(n),通常的实现是破坏性的in-memory实现,即在给定的原数组上做破坏性排序。
选择排序的实现
原理讲了,笔者在此贴出实现代码供参考。样例代码和测试代码在笔者github上demo仓库里能找到。
/**
* 选择排序的实现类。
* @author toranekojp
*/
public final class SelectionAscendingSort extends AbstractAscendingSort {
@Override
protected void doSort(int[] nums) {
assert nums != null;
final int boundle = nums.length;
for (int i = 0; i < boundle; i++) {
int minNum = nums[i]; // 记录本轮最小数字
int minIndex = i; // 记录本轮最小数字的下标。
// 枚举剩余数组,找出最小数字。
for (int j = i + 1; j < boundle; j++) {
if (nums[j] < minNum) {
// 找到更小的替换就当前记录的信息。
minNum = nums[j];
minIndex = j;
}
}
// 通过交换把最小的数字挪到本轮搁置位i。
swap(nums, i, minIndex);
// 继续下一轮直到所有元素都被处理。
}
}
}
结语
选择排序虽然简单,但是确实我们通过程序实现排序的第一步,因为这和现实的排序很接近。理解并实现此算法会增加你的编程基本功。但是需要注意的是在工作中基本不会用到此类排序算法。