选择排序也是十大排序算法中的一种,他是将整个数组从头到尾全部扫描一遍,然后选择最小的与第一位进行交换,接着再在剩下的元素中进行扫描,直到扫描完毕,最终,得到一个有序数列。这是一种思路非常简单的排序算法。我们先简单的实现一下,代码如下:
public static void main(String[] args) { int[] arr = { 1, 3, 4, 2, 6, 7, 8, 0, 5 }; int n = arr.length - 1;// 经过n-1次提取最小最大值 long startTime = System.nanoTime(); // 获取开始时间 for (int i = 0; i < arr.length - 1; i++) { int min = i; for (int j = i + 1; j < arr.length; j++) { if (arr[min] > arr[j]) { min = j; } } if (min != i) { int tmp = arr[min]; arr[min] = arr[i]; arr[i] = tmp; } } long endTime = System.nanoTime(); // 获取结束时间 System.out.println("排序結果:" + Arrays.toString(arr)); System.out.println("程序运行时间: " + (endTime - startTime) + "ns"); }
打印结果如下:
排序結果:[0, 1, 2, 3, 4, 5, 6, 7, 8] 程序运行时间:3100ns
最基本的选择排序是一次将一个元素进行位置的确定,那么我们可不可以一次确定两个元素的位置呢?
优化代码如下:
public static void main(String[] args) { int[] arr = { 1, 3, 4, 2, 6, 7, 8, 0, 5 }; long startTime = System.nanoTime(); // 获取开始时间 // 最小值下标 int min = 0; // 最大值下标 int max = 0; int left = 0; int right = arr.length - 1; int j = 0; // 循环size-1次 while (left < right) { max = left; min = right; // 确定最大值下标以及最小值下标 for (j = left; j <= right; j++) { if (arr[j] > arr[max]) { max = j; } if (arr[j] < arr[min]) { min = j; } } // 将最大值插到最后 if (max != right) { int tmp = arr[max]; arr[max] = arr[right]; arr[right] = tmp; } // 防止minpos在最大值要插入的位置 if (min == right) { min = max; } // 将最小值插到最前面 if (min != left) { int tmp = arr[min]; arr[minpos] = arr[left]; arr[left] = tmp; } left++; right--; } long endTime = System.nanoTime(); // 获取结束时间 System.out.println("排序結果:" + Arrays.toString(arr)); System.out.println("程序运行时间: " + (endTime - startTime) + "ns"); }
打印结果如下:
排序結果:[0, 1, 2, 3, 4, 5, 6, 7, 8] 程序运行时间:2600ns
有朋友要问了,为什么要加上这段代码呢:
if (min == right) { min = max; }
比如数组{ 1, 3, 4, 2, 6, 7, 8, 0, 5 };max=0,min=8;
max!=8,交换0和8,[0, 1, 2, 3, 4, 5, 6, 7, 8]但是max依旧是0,minpos依旧是8,min!=0,又再次交换0和8.
所以为防止min在最大值要插入的位置,要加上上面这块代码。