选择排序(Selection Sort)
选择排序(Selection-sort)是一种简单直观的排序算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
算法描述
n个记录的直接选择排序可经过n-1趟直接选择排序得到有序结果。具体算法描述如下:
- 初始状态:无序区为R[1…n],有序区为空;
- 第i趟排序(i=1,2,3…n-1)开始时,当前有序区和无序区分别为R[1…i-1]和R(i…n)。该趟排序从当前无序区中-选出关键字最小的记录
R[k],将它与无序区的第1个记录R交换,使R[1…i]和R[i+1…n)分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区;
n-1趟结束,数组有序化了。
动图演示
代码实现
public static void selectionSort(int[] array){
int len=array.length;
int minIndex;
for (int i = 0; i < len-1; i++) {
minIndex=i;
for (int j = i+1; j < len; j++) {
if(array[j]<array[minIndex]){
minIndex=j;
}
}
if(minIndex!=i){
int temp=array[minIndex];
array[minIndex]=array[i];
array[i]=temp;
}
}
}
算法分析
表现最稳定的排序算法之一,因为无论什么数据进去都是O(n2)的时间复杂度,所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧。理论上讲,选择排序可能也是平时排序一般人想到的最多的排序方法了吧。
代码思路讲解
冒泡排序可以说是十大排序算的鼻祖,几乎后面所有的排序算法都是基于冒泡排序一步步改进,所做的优化。选择排序也不例外。
这就要从冒泡排序的缺点说起:冒泡通过从头遍历,比较相邻元素,满足条件则换位的方式实现排序。
每次比较,一旦满足左>右则立刻发生换位操作。这样一轮下来,最坏可能要换位length-1次
而选择排序采用标记,延迟换位。减少了算法排序中的元素换位操作次数。提升算法效率
- 首先,选择排序也是两两比较排序。每轮选出一个该轮的最小数,追加到左侧有序部分的尾部。所以对于长度为n的数组,需要排序n-1轮
- 由于每轮会得出一个最小数,将其与该轮用来比较的元素换位(从宏观上只关注左侧有序序列构建方式来看,好比每轮往左侧有序列表的尾部追加元素一样),下一轮待排序元素便从上一轮用来比较的元素下标+1开始。也就是内层循环的j=i+1开始到数组的最后一个元素。
- 我们先定义一个minIndex变量,用来存储每一轮排序得出的最小值下标。
- 待该轮遍历比较结束,判断minIndex最小值下标和用来做比较的元素下标是否一致。不一致则换位,否则不换位(一致说明用来比较的元素是该轮的最小值,不用动。然后指针右移)。
- 这样每一轮依照这种方式,进行比较,延迟换位排序实现对无列表的排序。
注意:
选择排序是不稳定排序。为什么这么说呢?假设有一个数组`array={1,2,5,5,3}
这里省略具体排序细节
1.第一轮排序,用1和右侧所有元素比较,1最小,不换位array={1,2,5,5,3}
2.第二轮排序,用2和2后面的所有元素比较,2最小,不换位array={1,2,5,5,3}
3.第三轮排序,用第三个5和其后面元素比较,3最小,换位array={1,2,3,5,5}
4.注意,本来在下标2位置的5和元素3(下标4)换位后,被移动到了数组末尾。而这个5和下标3位置的5大小相等。原本在下标4位置的5的前面,换位后被移动到了后面
5.第四轮,用下标3位置的5和最后一个元素5比较,相等,不换位。得出数组array={1,2,3,5,5}
在这个过程中原本在前面的5,在排序结束后被移动到了同为5的另一个元素后面。实际中,对于基本类型这点倒不会引发问题。但对于引用类型,比如我们使用选择排序对一个对象列表,据其元素的某一个字段name,进行排序(除name外其他属性字段值不同)。会发现得出的列表。相同name值得元素a,b
有时a在前,有时b在前。所以当我们对引用类型序列进行排序并着重关注其顺序时,不稳定排序则不适用。应选用稳定排序
总结
其实,可以看出。上节所讲的冒泡排序和本章的选择排序都可看做:通过遍历一个待排序无序序列,通过比较换位,来在序列的一段构建有序序列的方式来实现排序。关于冒泡排序,之前只示例了一个最简单的优化排序算法,还有很多比如如鸡尾酒排序(使用分治法进行双向冒泡排序)等等,有很多基于经典算法衍生出来的优化算法,名字千奇百怪。后续我也会陆续更新和完善。
文章有任何语言表达不当,或者讲解枯燥晦涩的地方也望有缘的读者可以提出。本人将不胜感激,并努力修正。
关于算法的理论和动图资料借鉴:https://www.cnblogs.com/onepixel/articles/7674659.html