算法介绍与思路推演
最容易想到的排序,给你一串数字,如何按照从小到大排序。我们可以从数字中找出最小的数,把它从旧的数据中剔除,放在新数组的第一位,然后从余下的数字中再找出最小的,放到第二位,这样一直找,直到原数组还剩下一位的时候,把这一位直接放到新数组的最后一位。
我们也可以不新建数组,没有必要浪费这一倍的空间,在找到最小的数之后,把该位置和第一位互换,然后找到次小的和第二位互换,直到还剩下一位。
推演代码的时候,先推演大结构,再推演细节。
推演细节的时候,从一般到特殊,实在想不出来,构建一个假数组数据推一下就行了。
尽量写直白的代码,和算法思路相同的代码,可以后期去合并逻辑,但是一开始最好直接写。
思路:
1、两层循环,外层循环控制次数,内层循环控制寻找与交换
2、第一次从[0到n)中找出最小的位置,然后将最小位置和0互换,第二次从[1到n)中找出最小的位置,然后和1互换,直到倒数第二位(下标为n-2)
3、交换的方法会出现很多次,我们最终应该将这个方法抽出来。
Java代码实现:
public static void main(String[] args) {
int[] arr = new int[]{10, 1, 4, 2, 8, 3, 5};
System.out.println(Arrays.toString(selectSort(arr)));
}
private static int[] selectSort(int[] arr){
// 外层循环控制次数,直到倒数第二位,所以是小于arr.length - 1
for(int i = 0; i < arr.length - 1; i++){
// 设置idx为i
int idx = i;
// 循环从idx+1开始进行比较,一直比较到最后一位
for(int j = idx + 1; j < arr.length; j++){
if(arr[j] < arr[idx] ){
idx = j;
}
}
// 如果找到的位置不是原始的位置,才进行交换
if(idx != i){
swap(arr, i, idx);
}
}
return arr;
}
/**
* 交换元素
* @param arr
* @param i
* @param j
*/
private static void swap(int[] arr, int i, int j){
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
时间复杂度:
比较次数为:1 + 2 + 3 + 4 + (n-1) = n * (n-1) /2 ,去除常数,也就是O(n^2),无论最好最坏情况都是O(n^2)次
交换次数:最好情况下,本身数组就是按次序的,交换次数为0,完全反序,交换次数为n-1,也就是介于0~n-1之间。
稳定性:
跨元素交换,不稳定。
假设数据为5 5 9 1,一次交换后会变成1 5 9 5,前面的一个5会跑到后面去,也就是不稳定,因为1 5 进行交换的时候,并不会考虑其它的。一般存在不相邻的元素交换的排序算法都是不稳定的。