1. 简述
不太会写,百度百科介绍的已经很详细,可以查看:baike.baidu.com/item/%E9%80… 选择排序的基本思路为:
- 从数组 0 ~ n-1 选出最小的值,放到 0 位置
- 从数组 1 ~ n-1 选出最小的值,放到 1 位置
- ... n. 从数组 n-1 ~ n-1 选出最小的值,放到 1 位置
2. 实现
package com.omg.sort;
import java.util.Arrays;
/**
* @description: 选择排序
* 流程:
* 第一步:0 ~ n-1 找到最小值,在哪,放到 0 位置上
* 第二步:1 ~ n-1 找到最小值,在哪,放到 1 位置上
* 第三步:2 ~ n-1 找到最小值,在哪,放到 2 位置上
* ...
* 第n步:n-1 ~ n-1 找到最小值,在哪,放到 n-1 位置
*/
public class Code01_SelectionSort {
public static void selectionSort(int[] arr){
if (null == arr || arr.length <= 1){
return;
}
for (int i = 0; i < arr.length; i++){
int minIndex = i;
for (int j = i+1; j < arr.length; j++){
if (arr[j] < arr[minIndex]){
minIndex = j;
}
}
if (i != minIndex){
swap(arr, i, minIndex);
}
}
}
/**
* @description: 交换数组中 i 和 j 位置的元素
*/
public static void swap(int[] arr, int i, int j){
arr[i] = arr[i]^arr[j];
arr[j] = arr[i]^arr[j];
arr[i] = arr[i]^arr[j];
}
/**
* @description: 对数器,为了验证实现是否正确
*/
public static void comparator(int[] arr) {
Arrays.sort(arr);
}
/**
* @description: 生成随机数组,用来测试排序,并与对数器比较结果
* @param maxSize 数组的最大长度
* @param maxValue 数组中元素的取值区间 [-maxValu, maxValu]
*/
public static int[] generateRandomArray(int maxSize, int maxValue){
// Math.random() [0,1)
// Math.random() * N [0,N)
// (int)(Math.random() * (N+1)) [0, N-1]
int size = (int)(Math.random()*(maxSize+1));
int[] arr = new int[size];
for (int i=0; i<arr.length; i++){
// 数据内元素第区间为 [-maxValue, maxValue]
arr[i] = (int)(Math.random()*(maxValue+1)) - (int)(Math.random()*(maxValue+1));
}
return arr;
}
/**
* @description: 数组拷贝,创建一个相同的数组,用于对数器排序比较
*/
public static int[] copyArray(int[] arr){
if (arr == null) {
return null;
}
int[] res = new int[arr.length];
for (int i=0; i<arr.length; i++){
res[i] = arr[i];
}
return res;
}
/**
* @description: 判断两个数组是否相同
*/
public static boolean isEqual(int[] arr1, int[] arr2) {
if (arr1 == arr2){
return true;
}
if (arr1.length != arr2.length){
return false;
}
if (arr1 != null && arr2 != null){
for (int i=0; i<arr1.length; i++){
if (arr1[i] != arr2[i]){
return false;
}
}
}
return true;
}
/**
* @description: 打印数组,如果排序结果和对数器的结果不一致可以打印出来,方便分析问题
*/
public static void printArray(int[] arr) {
if (arr == null) {
return;
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
public static void main(String[] args) {
// 测试次数
int testTime = 50000;
// 数组最大长度
int maxSize = 100;
// 数组内元素取值区间 [-100, 100]
int maxValue = 100;
boolean succeed = true;
for (int i=0; i<testTime; i++){
int[] arr1 = generateRandomArray(maxSize, maxValue);
int[] arr2 = copyArray(arr1);
selectionSort(arr1);
comparator(arr2);
// 自己实现的选择排序结果与对数器结果比较,如果不一致 break 跳出循环
if (!isEqual(arr1, arr2)){
succeed = false;
printArray(arr1);
printArray(arr2);
break;
}
}
System.out.println(succeed ? "Nice!" : "Fucking fucked!");
}
}
3. 时间复杂度与空间复杂度
3.1 时间复杂度分析
- 从数组 0 ~ n-1 选出最小的值,放到 0 位置: 共操作 n 次
- 从数组 1 ~ n-1 选出最小的值,放到 1 位置: 共操作 n-1 次
- ... n. 从数组 n-1 ~ n-1 选出最小的值,放到 1 位置: 共操作 1 次
通过上面的步骤分析可知,选择排序的时间复杂度为:
最终可以写为 的形式,最终忽略掉常常数项,时间复杂度为 O(n^2)
3.2. 空间复杂度
查看选择排序代码,只有一个变量用来记录最小值的 index。 时间复杂度为 O(1)