笔者在上一篇博客中回顾了下冒泡排序(Bubble-Sort),这里写篇博客讲讲选择排序(Selection-Sort)。选择排序在每一次的迭代中,不直接交换相邻元素,而是从数组中选择出当前数组中的最小值(最大值)的索引,并于当前待排序位置的索引进行比较。若不相等,则交换之,亦即会出现如下情况
当前最小值: 3 -> [7, 36, 18, 7, 39, 35, 12, 29, 37, 3, 16, 38, 11, 26, 27, 33, 12, 7, 39, 25]
当前最小值: 7 -> [3, 36, 18, 7, 39, 35, 12, 29, 37, 7, 16, 38, 11, 26, 27, 33, 12, 7, 39, 25]
而冒泡排序则是在每一次迭代中,对不满足条件的相邻元素进行交换从而确保每次迭代都会将最小值或者最大值“冒泡”到数组前面或者后面。算法本身不难,在给出相应代码实现之前,先简单分析下其时间复杂度。设数组长度为n,其时间复杂度可以表示为O(n^2),且一般情况下,选择排序算法都是稳定的,除非将判断条件之一
array[index] > array[i]
修改为
array[index] >= array[i]
完整代码如下
import com.sun.istack.internal.NotNull;
import java.util.Arrays;
import java.util.Random;
/**
* A demo of {@code SelectionSort}.
*
* @author Mr.K
*/
public class SelectionSort {
public static void main(String[] args) {
int N = 20;
int[] numbers = new int[N];
Random random = new Random();
for (int i = 0; i < N; i++) {
numbers[i] = random.nextInt(2 * N);
}
System.out.println(Arrays.toString(numbers) + "\n");
selectionSort(numbers);
System.out.println("\n" + Arrays.toString(numbers));
}
/**
* Accepts an array and sorts the specified array by algorithm {@code SelectionSort}.
* This is one version of {@code SelectionSort} where the minimum number will be
* selected from the remaining array in each iteration and that number will be moved
* to the head of the array, in ascending order.
* <ul>
* <li>This algorithm starts from index 0 and to the last index of the specified
* array.</li>
* <li>In each iteration, the first step is to find the minimum number from i
* (inclusive), which is the number of iteration, to the last index(exclusive)
* of the array.</li>
* <li>If current cursor index does not equal to the index of the minimum number
* of the remaining array, then exchange these two number by <em>Xor</em>.</li>
* <li>Cause the condition to find the minimum number of the remaining array is
* <blockquote>
* index = array[index] > array[i] ? i : index;
* </blockquote>
* which means only when a certain number is less than current number, exchange
* will be implemented. So {@code SelectionSort} is stable. If exchanges happen
* when there are two number with the same value, {@code SelectionSort} becomes
* unstable.</li>
* </ul>
* From the process, there's no doubt that the cost of time of {@code SelectionSort}
* equals O(n^2) for there are two <em>For-Loops</em>, which may become a bottleneck
* in the bad cases.
*
* @param numbers specified array to be sorted
*/
public static void selectionSort(@NotNull int[] numbers) {
for (int i = 0; i < numbers.length; i++) {
int indexOfMinNumber = findMinNumberIndex(numbers, i, numbers.length);
System.out.println("第" + String.format("%2d", i) + "步, 当前最小值: " +
String.format("%2d", numbers[indexOfMinNumber]) + " -> " + Arrays.toString(numbers));
if (i != indexOfMinNumber) {
int temp = numbers[i] ^ numbers[indexOfMinNumber];
numbers[i] = temp ^ numbers[i];
numbers[indexOfMinNumber] = temp ^ numbers[indexOfMinNumber];
}
}
}
/**
* Accepts an array, finds the index of the minimum number of the specified array in
* the range from start index(inclusive) to end index(exclusive) and returns the index.
* Be aware that only when a certain number is less than current number, exchange will
* happen to ensure that {@code SelectionSort} is stable.
*
* @param array specified array to find index of the minimum number
* @param start index of start position(inclusive)
* @param end index of end position(exclusive)
* @return index of the minimum number in the specified array
*/
public static int findMinNumberIndex(@NotNull int[] array, @NotNull int start, @NotNull int end) {
int index = start;
for (int i = start; i < end; i++) {
index = array[index] > array[i] ? i : index;
}
return index;
}
}
某次运行结果如下
[18, 12, 23, 33, 23, 6, 39, 31, 20, 4, 22, 22, 13, 27, 7, 9, 34, 29, 29, 34]
第 0步, 当前最小值: 4 -> [18, 12, 23, 33, 23, 6, 39, 31, 20, 4, 22, 22, 13, 27, 7, 9, 34, 29, 29, 34]
第 1步, 当前最小值: 6 -> [4, 12, 23, 33, 23, 6, 39, 31, 20, 18, 22, 22, 13, 27, 7, 9, 34, 29, 29, 34]
第 2步, 当前最小值: 7 -> [4, 6, 23, 33, 23, 12, 39, 31, 20, 18, 22, 22, 13, 27, 7, 9, 34, 29, 29, 34]
第 3步, 当前最小值: 9 -> [4, 6, 7, 33, 23, 12, 39, 31, 20, 18, 22, 22, 13, 27, 23, 9, 34, 29, 29, 34]
第 4步, 当前最小值: 12 -> [4, 6, 7, 9, 23, 12, 39, 31, 20, 18, 22, 22, 13, 27, 23, 33, 34, 29, 29, 34]
第 5步, 当前最小值: 13 -> [4, 6, 7, 9, 12, 23, 39, 31, 20, 18, 22, 22, 13, 27, 23, 33, 34, 29, 29, 34]
第 6步, 当前最小值: 18 -> [4, 6, 7, 9, 12, 13, 39, 31, 20, 18, 22, 22, 23, 27, 23, 33, 34, 29, 29, 34]
第 7步, 当前最小值: 20 -> [4, 6, 7, 9, 12, 13, 18, 31, 20, 39, 22, 22, 23, 27, 23, 33, 34, 29, 29, 34]
第 8步, 当前最小值: 22 -> [4, 6, 7, 9, 12, 13, 18, 20, 31, 39, 22, 22, 23, 27, 23, 33, 34, 29, 29, 34]
第 9步, 当前最小值: 22 -> [4, 6, 7, 9, 12, 13, 18, 20, 22, 39, 31, 22, 23, 27, 23, 33, 34, 29, 29, 34]
第10步, 当前最小值: 23 -> [4, 6, 7, 9, 12, 13, 18, 20, 22, 22, 31, 39, 23, 27, 23, 33, 34, 29, 29, 34]
第11步, 当前最小值: 23 -> [4, 6, 7, 9, 12, 13, 18, 20, 22, 22, 23, 39, 31, 27, 23, 33, 34, 29, 29, 34]
第12步, 当前最小值: 27 -> [4, 6, 7, 9, 12, 13, 18, 20, 22, 22, 23, 23, 31, 27, 39, 33, 34, 29, 29, 34]
第13步, 当前最小值: 29 -> [4, 6, 7, 9, 12, 13, 18, 20, 22, 22, 23, 23, 27, 31, 39, 33, 34, 29, 29, 34]
第14步, 当前最小值: 29 -> [4, 6, 7, 9, 12, 13, 18, 20, 22, 22, 23, 23, 27, 29, 39, 33, 34, 31, 29, 34]
第15步, 当前最小值: 31 -> [4, 6, 7, 9, 12, 13, 18, 20, 22, 22, 23, 23, 27, 29, 29, 33, 34, 31, 39, 34]
第16步, 当前最小值: 33 -> [4, 6, 7, 9, 12, 13, 18, 20, 22, 22, 23, 23, 27, 29, 29, 31, 34, 33, 39, 34]
第17步, 当前最小值: 34 -> [4, 6, 7, 9, 12, 13, 18, 20, 22, 22, 23, 23, 27, 29, 29, 31, 33, 34, 39, 34]
第18步, 当前最小值: 34 -> [4, 6, 7, 9, 12, 13, 18, 20, 22, 22, 23, 23, 27, 29, 29, 31, 33, 34, 39, 34]
第19步, 当前最小值: 39 -> [4, 6, 7, 9, 12, 13, 18, 20, 22, 22, 23, 23, 27, 29, 29, 31, 33, 34, 34, 39]
[4, 6, 7, 9, 12, 13, 18, 20, 22, 22, 23, 23, 27, 29, 29, 31, 33, 34, 34, 39]
上一篇-浅谈排序算法之冒泡排序。