八大排序之选择排序
一、基本思想
每次从待排记录中选出最小值放在有序记录的末尾。等每一个待排元素均被选出后,整个记录排序就完成了。
二、实现步骤
这里采用双向选择排序,每次从待排记录中选出最大值和最小值,最大值和待排记录的最后一位交换位置,最小值和待排记录的第一位交换位置。
注意,交换位置分如下情况:
1)最大值在最左边,最小值在最右边。直接将最大值最小值相互交换即可。
2)最大值在最左边,最小值在中间。必须先将最大值与最后一位交换,再将最小值与第一位交换。否则会出错,不信就试试。
3)最大值在中间,最小值在中间。随意谁先交换都行。
4)最小值在最右边,最大值在中间。必须先将最小值与第一位交换,再将最大值与最后一位交换。
5)最小值在最右边,最大值在最左边。不用交换。
对于上述5种情况,其实可以简化成如下情况来做。
一、如果max在最左边,
如果min在最右边,两者直接交换
否则,先交换max,再交换min
二、其他情况一律先交换min,再交换max。
max在最左,min在最右这种情况,由于两次交换,等同于没交换,所以不会出现错误。
三、实现代码
测试工具类 点击这里
package sort; import sort.util.*; /* 选择排序思路: 选择待排记录中最小值,放在左边 双向选择,一次遍历中选出最大值放在右边,选出最小值放在左边 时间复杂度:O(n2) 空间复杂度:O(1) 稳定性: 稳定 */ public class SelectSort implements ISort{ public void sort(int[] a) { int n = a.length; for(int i = 0; i < n / 2; i++) { int maxId = i; int minId = i; for(int j = i; j <= n - i - 1; j++) { if(a[j] > a[maxId]) {maxId = j;} if(a[j] < a[minId]) {minId = j;} } //根据maxId的位置走不同的交换顺序 int t = 0; if(maxId == i){ if(minId == n - 1 - i) { t = a[maxId]; a[maxId] = a[minId]; a[minId] = t; //max和min位于相反的位置上,直接将其交换 }else{ t = a[maxId]; a[maxId] = a[n-1-i]; a[n-1-i] = t; //max位于最左,先交换max t = a[minId]; a[minId] = a[i]; a[i] = t; //再交换min } }else{ t = a[minId]; a[minId] = a[i]; a[i] = t; //min位于最右和其他情况,先交换min t = a[maxId]; a[maxId] = a[n-1-i]; a[n-1-i] = t; } } } public static void main(String[] args) { int[] array = RandomArrayGenerator.getRandomArray(100 , 30); SortTestHelper.test(new SelectSort() , array); } }
测试结果:
四、总结分析
时间复杂度:O(n2)
空间复杂度:O(1)
选择排序是一种比较直观易懂的排序算法,时间复杂度不理想,但几乎不占空间。下篇将展示选择排序的改进算法 ----- 堆排序。