相对于冒泡排序,选择排序多一个变量,专门存储最小值、最大值的下标,等每轮次循环遍历结束后,才会进行两个元素的交换。这样比冒泡排序减少了交换次数。
1. 基本实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| public static void main(String[] args) { int[] arr = new int[]{189, -6, 0, 1, 34, 78}; selectionSort(arr); Arrays.stream(arr).forEach(System.out::println); }
public static void selectionSort(int[] arr) { int count = 0, length = arr.length, minIndex; for (int i = 0; i < length - 1; i++) { minIndex = i; for (int j = i + 1; j < length; j++) { if (arr[minIndex] > arr[j]) { minIndex = j; } count++; } int temp = arr[i]; arr[i] = arr[minIndex]; arr[minIndex] = temp; } System.out.println("循环进行了 " + count + " 次"); }
public static void swap(int[] arr, int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; }
循环进行了 15 次 -6 0 1 34 78 189
Process finished with exit code 0
|
2. 优化版本1
既然每轮遍历时找出了最小值,同时把最大值也顺便找出来。这就是二元选择排序的思想。
使用二元选择排序,每轮选择时记录最小值和最大值,可以把数组需要遍历的范围缩小一倍。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| public static void main(String[] args) { int[] arr = new int[]{189, -6, 0, 1, 34, 78}; selectionSort(arr); Arrays.stream(arr).forEach(System.out::println); }
public static void selectionSort(int[] arr) { int minIndex, maxIndex,count=0; for (int i = 0; i < arr.length / 2; i++) { minIndex = i; maxIndex = i; for (int j = i + 1; j < arr.length - i; j++) { if (arr[minIndex] > arr[j]) { minIndex = j; } if (arr[maxIndex] < arr[j]) { maxIndex = j; } count++; } if (minIndex == maxIndex) break; int temp = arr[i]; arr[i] = arr[minIndex]; arr[minIndex] = temp; if (maxIndex == i) maxIndex = minIndex; int lastIndex = arr.length - 1 - i; temp = arr[lastIndex]; arr[lastIndex] = arr[maxIndex]; arr[maxIndex] = temp; } System.out.println("循环进行了 " + count + " 次"); }
public static void swap(int[] arr, int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; }
循环进行了 9 次 -6 0 1 34 78 189
Process finished with exit code 0
|
总结
从代码可以看出,虽然二元选择排序最外层的遍历范围缩小了,但 for 循环内做的事情翻了一倍。也就是说二元选择排序无法将选择排序的效率提升一倍。但实测会发现二元选择排序的速度确实比选择排序的速度快一点点。