选择排序¶
一、算法描述¶
1.1 核心思想¶
- 数据分为已排序区间和未排序区间
- 从未排序区间中找到最小/最大的元素,放到到已排序区间的尾部
- 执行 n 轮后,所有未排序元素都会迁移到已排序区间中
1.2 细节解释¶
比如说,数组 [2, 7, 1, 4, 3, 6, 5]。
首先分成未排序和已排序区间,已排序区间一开始是空的:
已排序 未排序
___ ___ ___ ___ ___ ___ ___
| 2 | 7 | 1 | 4 | 3 | 6 | 5 |
首先找到未排序区间的最小值,也就是 1,将 1 迁移到已排序区间中:
已排序 未排序
___ ___ ___ ___ ___ ___ ___
| 1 | | 7 | 2 | 4 | 3 | 6 | 5 |
继续从未排序区间找最小值,得到 2,然后将 2 移动到已排序区间:
已排序 未排序
___ ___ ___ ___ ___ ___ ___
| 1 | 2 | | 7 | 4 | 3 | 6 | 5 |
以此类推,分别交换得到 3、4、5、6、7 的最终位置:
已排序 未排序
___ ___ ___ ___ ___ ___ ___
| 1 | 2 | 3 | | 4 | 7 | 6 | 5 |
已排序 未排序
___ ___ ___ ___ ___ ___ ___
| 1 | 2 | 3 | 4 | | 7 | 6 | 5 |
已排序 未排序
___ ___ ___ ___ ___ ___ ___
| 1 | 2 | 3 | 4 | 5 | | 6 | 7 |
已排序 未排序
___ ___ ___ ___ ___ ___ ___
| 1 | 2 | 3 | 4 | 5 | 6 | | 7 |
已排序 未排序
___ ___ ___ ___ ___ ___ ___
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
经过 n 轮交换,数组就排好序了。
二、算法实现¶
public void selectSort(int[] arr) {
int n = arr.length;
for (int i = 0; i < n; i++) {
// 寻找未排序区间内的最小值
int min = i;
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[min]) {
min = j;
}
}
// 将最小值插入到已排序区间的末尾
swap(arr, min, i);
}
}
执行过程如下:
===== 初始数组 =====
[0, 3, 1, 6, 2, 5, 4]
=====第 1 轮插入=====
[0, 3, 1, 6, 2, 5, 4]
=====第 2 轮插入=====
[0, 1, 3, 6, 2, 5, 4]
=====第 3 轮插入=====
[0, 1, 2, 6, 3, 5, 4]
=====第 4 轮插入=====
[0, 1, 2, 3, 6, 5, 4]
=====第 5 轮插入=====
[0, 1, 2, 3, 4, 5, 6]
=====第 6 轮插入=====
[0, 1, 2, 3, 4, 5, 6]
=====第 7 轮插入=====
[0, 1, 2, 3, 4, 5, 6]
三、算法分析¶
3.1 时间复杂度¶
- 最好时间复杂度:O(n^2)
- 最坏时间复杂度:O(n^2)
- 平均时间复杂度:O(n^2)
3.2 空间复杂度¶
- 空间复杂度:O(1)
- 原地算法
3.3 稳定性¶
- 不稳定排序算法
附录¶
/**
* 选择排序
* <p>
* 时间复杂度:最好 O(n^2) 最差 O(n^2) 平均 O(n^2)
* <p>
* 空间复杂度:O(1)
* <p>
* 稳定性:不稳定
*
* @author weijiaduo
* @since 2022/7/21
*/
public class SelectSort implements Sort {
@Override
public void sort(int[] arr) {
int n = arr.length;
for (int i = 0; i < n; i++) {
// 寻找未排序区间内的最小值
int min = i;
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[min]) {
min = j;
}
}
// 将最小值插入到已排序区间的末尾
swap(arr, min, i);
}
}
}