2. 选择排序
2.1 概念
-
什么是选择排序?
选择排序(SelectionSort)是将数组分为两个子集:已排序的和未排序的,每一轮从未排序的子集中选出最小的元素,放入已排序的子集的末尾。重复以上步骤,直到整个数组有序。
-
动画展示(此动画为网上图片,拿来借鉴一下,便于大家理解)
2.2 代码演示
-
初步实现选择排序
public class SelectionSort01 { public static void main(String[] args) { int[] arr = {2, 4, 8, 6, 5, 7, 3, 1, 9}; selection(arr); } public static void selection(int[] arr){ //j表示该轮找到的最小元素要交换到的目标位置索引,即第一次为数组下标为0的位置,第二次为数组下标为1... for (int j = 0; j < arr.length-1; j++) { //minIndex表示该轮找到的最小值的索引,初始值为j int minIndex = j; for (int i = minIndex + 1; i < arr.length; i++) { if (arr[minIndex] > arr[i]){ minIndex = i; } } if (minIndex != j){ swap(arr,j,minIndex); } System.out.println(Arrays.toString(arr)); } } public static void swap(int[] arr, int i, int j) { int t = arr[i]; arr[i] = arr[j]; arr[j] = t; } }
-
输出结果:
-
具体分析
2.3 优化
-
优化思路:原来是每一轮找出该数组中的最小元素,可以优化为每一轮找出该数组中的最小元素和最大元素,分别放到数组的两端,这样就能将遍历的趟数减少一半。
-
代码实现:
public class SelectionSort02 { public static void main(String[] args) { int[] arr = {2, 14, 4, 8, 13, 6, 5, 15, 7, 12, 11, 3, 1, 9, 10}; selection(arr); } public static void selection(int[] arr) { //初始化第一次找到的最小和最大值要交换到的目标位置,第一次为数组起始和末尾 int left = 0; int right = arr.length - 1; while (left < right) { //初始化最小元素和最大元素的索引,初始值为left和right int min = left; int max = right; for (int i = left; i <= right; i++) { if (arr[i] < arr[min]) { min = i; } if (arr[i] > arr[max]) { max = i; } } swap(arr, left, min); //在最小值与目标位置交换位置后,进行判断,如果最小值要交换的目标位置上的值刚好是最大值,(此时相当于 最小值与最大值换位置)则应该把最小值原来的位置赋给最大值,才能保证最大值的索引是正确的 if (max == left) { max = min; } swap(arr, right, max); left++; right--; System.out.println(Arrays.toString(arr)); } } public static void swap(int[] arr, int i, int j) { int t = arr[i]; arr[i] = arr[j]; arr[j] = t; } }
-
输出结果:
-
如果按照优化前的代码要进行14次排序,进行优化后只需要进行7次排序。
选择排序与冒泡排序做比较:
- 二者的平均时间复杂度都是O(n²)。
- 选择排序一般要快于冒泡排序,因为选择排序的的交换次数更少。
- 如果集合的有序度高,冒泡排序优于选择排序。
- 冒泡排序是稳定的,选择排序是不稳定的。