选择排序是一种排序算法,每次迭代时,从未排序的列表中选择最小的一个,然后把这个元素放在未排序列表的前面。
选择排序的工作原理
- 选择第一个元素作为
minimum
- 对比:
minimum和第二个元素做对比。如果第二个元素比minimum小,把第二个元素设置为minimum
重复步骤2:对比 minimum 和第三个元素,如果第三个元素更小,把第三个元素设置为 minimum,否则,什么都不做。
直到最后一个元素为止。
- 交换:将
minimum和最前面的未排序的元素交换。每轮迭代后,minimum被放在未排序列表的最前面了。
- 对于每次迭代,索引从第一个未排序的元素开始,前三个步骤会一直重复,直到每个元素都排好序为止。
选择排序代码实现
JavaScript
const selectionSort = (array) => {
const size = array.length;
for (let step = 0; step < size - 1; step++) {
let min_idx = step;
for (let i = step + 1; i < size; i++) {
// 每次循环中选择值最小的元素
if (array[i] < array[min_idx]) {
min_idx = i;
}
}
// 交换,将最小值放在正确的位置
[array[step], array[min_idx]] = [array[min_idx], array[step]];
}
};
// test
const data = [20, 12, 10, 15, 2];
selectionSort(data);
console.log(data); // [2,10,12,15,20]
Java
/**
* 支持 import Java 标准库 (JDK 1.8)
*/
import java.util.*;
import java.util.Arrays;
class SelectionSort {
void selectionSort(int array[]) {
int size = array.length;
for (int step = 0; step < size - 1; step++) {
int min_idx = step;
for (int i = step + 1; i < size; i++) {
if (array[i] < array[min_idx]) {
min_idx = i;
}
}
// 交换:把最小值放在正确的位置
int temp = array[step];
array[step] = array[min_idx];
array[min_idx] = temp;
}
}
}
public class Main {
public static void main(String []args) {
int[] data = { 20, 12, 10, 15, 2 };
SelectionSort ss = new SelectionSort();
ss.selectionSort(data);
System.out.println("升序排列如下:");
System.out.println(Arrays.toString(data));
}
}
复杂度分析:
| 名字 | 最好 | 平均 | 最坏 | 空间复杂度 | 是否稳定 |
|---|---|---|---|---|---|
| 选择排序 | O(n^2) | O(n^2) | O(n^2) | O(1) | 否 |
复杂度分析详解
时间复杂度
选择排序对比相邻的元素:
| 每一轮 | 对比的次数 |
|---|---|
| 第一轮迭代 | (n - 1) |
| 第二轮迭代 | (n - 2) |
| ...... | ...... |
| 最后一轮迭代 | 1 |
因此,对比的次数为:
(n-1) + (n-2) + (n-3) + ...... + 1 = n(n-1)/2
结果相当于 n^2,因此,时间复杂度为 O(n^2)
我们也可以通过观察代码,选择排序经过两轮循环,因此,时间复杂度为 O(n^2)。
空间复杂度
- 空间复杂度为
O(1),因为需要一个额外的变量用于交换
选择排序的应用
选择排序在以下几种情况下适用:
- 一个需要排序的小列表
- 交换需要的花费无关紧要
- 检查每个元素都是必要的
总结
回顾一下,选择排序需要四个步骤:
- 将第一个元素作为
minimum - 对比:将
minimum与其余元素进行对比,设置新的minimum - 交换:迭代结束后,将
minimum与最前面的未排序的元素交换 - 重复前三个步骤,直到所有元素都排好序为止。