选择排序(selection sort)的工作原理非常简单:开启一个循环,每轮从未排序区间选择最小的元素,将其放到已排序区间的末尾。
目录
一.算法流程
设数组的长度为 n 。
- 初始状态下,所有元素未排序,即未排序(索引)区间为 [0,n−1] 。
- 然后进入到排序方法当中,从未排序区间里边选出最小值,然后放到排序区间里边,未排序区间逐渐减小,排序区间逐渐增大,最后只剩一个元素在数组末端,此时该元素即为最大值。
- 所以有两层循环,外部循环负责构建排序区间,范围是[0,n-2],内层循环负责找到未排序区间中的最小值然后将其放入排序区间当中。最后最小值与未排序区间的第一个元素相互交换位置,排序区间增一,未排序区间减一。
在代码中,我们用 k 来记录未排序区间内的最小元素:
public class Demo{
public static void main(String[] args) {
int[] nums={8,4,5,2,7,9,0};
selectionSort(nums);
for (int i = 0; i < nums.length; i++) {
System.out.print(nums[i]+" ");
}
}
/* 选择排序 */
void selectionSort(int[] nums) {
int n = nums.length;
// 外循环:未排序区间为 [i, n-1]
for (int i = 0; i < n - 1; i++) {
// 内循环:找到未排序区间内的最小元素
int k = i;
for (int j = i + 1; j < n; j++) {
if (nums[j] < nums[k])
k = j; // 记录最小元素的索引
}
// 将该最小元素与未排序区间的首个元素交换
int temp = nums[i];
nums[i] = nums[k];
nums[k] = temp;
}
}
}
二.算法特性
- 时间复杂度为 O(n2)、非自适应排序:外循环共 n−1 轮,第一轮的未排序区间长度为 n ,最后一轮的未排序区间长度为 2 ,即各轮外循环分别包含 n、n−1、…、3、2 轮内循环,求和为 (n−1)(n+2)2 。
- 空间复杂度为 O(1)、原地排序:指针 i 和 j 使用常数大小的额外空间。
- 非稳定排序:如图 11-3 所示,元素
nums[i]
有可能被交换至与其相等的元素的右边,导致两者的相对顺序发生改变。