选择排序—简单选择排序
选择排序的基本思想是:每一趟从待排序的记录中选出关键字最小的记录,顺序放在已排好序的子系列的最后,直到全部记录排序完毕。简单选择排序也叫直接选择排序。
基本算法:
将给定待排序序列A[0....n],第一次从A[0]~A[n-1]中选取最小值,与A[0]交换,第二次从A[1]~A[n-1]中选取最小值,与A[1]交换,....,第i次从A[i-1]~A[n-1]中选取最小值,与A[i-1]交换,.....,第n-1次从A[n-2]~A[n-1]中选取最小值,与A[n-2]交换,总共通过n-1次,得到一个按排序码从小到大排列的有序序列。
直接选择排序和直接插入排序类似,都将数据分为有序区和无序区,所不同的是直接插入排序是将无序区的第一个元素直接插入到有序区以形成一个更大的有序区,而直接选择排序是从无序区选一个最小的元素直接放到有序区的最后。
简单选择排序示例:
假设给定待排序数组A[0......5]={ 2,7,6,3,1,5 }
第一趟:i=0,在无序区A[0......5]中,index=4,元素最小 a[0] 和 a[4] 进行交换。得到序列:{ 1,7,6,3,2,5 }
第二趟:i=1,在无序区A[1......5]中,index=4,元素最小 a[1] 和 a[4] 进行交换。得到序列:{ 1,2,6,3,7,5 }
第三趟:i=2,在无序区A[2......5]中,index=3,元素最小 a[2] 和 a[3] 进行交换。得到序列:{ 1,2,3,6,7,5 }
第四趟:i=3,在无序区A[3......5]中,index=5,元素最小 a[3] 和 a[5] 进行交换。得到序列:{ 1,2,3,5,7,6 }
第五趟:i=4,在无序区A[4......5]中,index=5,元素最小 a[4] 和 a[5] 进行交换。得到序列:{ 1,2,3,5,6,7 }
第六趟:i=5,在无序区A[5......5]中,最后一个元素,不要交换。得到排好的序列:{ 1,2,3,5,6,7 }
按照选择排序算法:
public static void selectSort(int [] arr){ int len = arr.length; for(int i=0;i<len-1;i++){ int min = i; for(int j = i+1;j<len;j++){ if(arr[j]<arr[min]){ min =j; } } if(min != i){ int temp = arr[i]; arr[i] = arr[min]; arr[min] = temp; } } }
算法复杂度
1 时间复杂度O(n^2)
选择排序耗时的操作:比较+交换位置。时间复杂度如下:
比较次数与关键字的初始状态无关,总的比较次数N=(n-1)+(n-2)+...+1=n*(n-1)/2,最好和最坏情况下都为O(n^2)
2 空间复杂度
由于需要一个临时变量来交换元素位,所需开辟的辅助空间跟输入数组规模无关,所以空间复杂度为:O(1)。
3 稳定性
选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n-1个元素,第n个元素不用选择了,因为只剩下它一个最大的元素了。那么,在一趟选择,如果一个元素比当前元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后稳定性就被破坏了。比较拗口,举个例子,序列5 8 5 2 9,我们知道第一遍选择第1个元素5会和2交换,那么原序列中两个5的相对前后顺序就被破坏了,所以选择排序是一个不稳定的排序算法。