选择排序
基本介绍
选择式排序也属于内部排序法,是从欲排序的数据中,按指定的规则选出某一元素,再依规定交换位置后达到排序的目的。
排序思想
选择排序(select sorting) 也是一种简单的排序方法。它的基本思想是:
第一次:从一个array数组中找到最小值与array[0]交换,也就是说不是像冒泡那样找到小的就交换,而是遍历了数组,找到最小的和array[0]交换,一次只发生一次交换
第二次:从array数组的array[1]~~~array[n-1]中找到最小值,与array[1]交换,这个过程中也是只发生一次交换
第三次:array[2]变成最小值。。。。依次类推
总共通过n-1次,得到一个按排序码从小到大排序的有序序列
思路
第一轮:将第一个位置当成最小数,开始循环遍历余下数组,比他小的更新成最小值,再往后找比现在这个还小的,一轮下来,找到最小的,开始交换
第二轮:将第二个位置当成最小数,开始循环遍历余下数组,往后面比较,发现比他小的,在更新最小值,再往后,找到剩余数中最小的数,遍历完之后,和第一个位置交换
第三轮:同理,从第三个位置开始
….
直到n-1轮
请听题:
现有科大学生十位,颜值分别是[100,10,35,24,16,79,4,2,57,80],请使用选择排序从低到高进行排序
代码
推导过程:
/**
* @author 王庆华
* @version 1.0
* @date 2020/12/21 21:32
* @Description TODO
* @pojectname 简单选择排序
*/
public class SelectSort {
public static void main(String[] args) {
int[] array = {
100,10,35,24,16,79,4,2,57,80};
selectSort(array);
}
//选择排序算法
public static void selectSort(int[] array){
//逐步推到方式
//第一轮排序
//原始数组[100,10,35,24,16,79,4,2,57,80]
//结果:[2,10,35,24,16,79,4,100,57,80]
int minIndex = 0;//用来存放,最小值的下标
int min = array[0];//假定现在最小值是数组第一个 也充当了中间值,来交换
for (int i = 0+1; i < array.length ; i++) {
if (min > array[i]){
//说明我们的假定最小值不是最小值
min = array[i]; //重置最小值
minIndex = i; //重置最小值索引
}
}
//循环结束,开始交换
if (minIndex != 0) {
array[minIndex] = array[0];
array[0] = min;
}
System.out.println("第一轮后:"+ Arrays.toString(array));
//第一轮后:[2, 10, 35, 24, 16, 79, 4, 100, 57, 80]
//第二轮排序
minIndex = 1;//用来存放,最小值的下标
min = array[1];//假定现在最小值是数组第一个 也充当了中间值,来交换
for (int i = 1+1; i < array.length ; i++) {
if (min > array[i]){
//说明我们的假定最小值不是最小值
min = array[i]; //重置最小值
minIndex = i; //重置最小值索引
}
}
//循环结束,开始交换
if (minIndex != 1) {
array[minIndex] = array[1];
array[1] = min;
}
System.out.println("第二轮后:"+ Arrays.toString(array));
//第二轮后:第二轮后:[2, 4, 35, 24, 16, 79, 10, 100, 57, 80]
//依次类推
}
}
在推导过程中,我们发现我们每次for循环之前,开始的标记,比上一轮for循环开始的位置+1了
那么我们可以用for循环来解决
/**
* @author 王庆华
* @version 1.0
* @date 2020/12/21 21:32
* @Description TODO
* @pojectname 简单选择排序
*/
public class SelectSort {
public static void main(String[] args) {
int[] array = {
100,10,35,24,16,79,4,2,57,80};
System.out.println("排序前"+Arrays.toString(array));
selectSort(array);
System.out.println("排序后"+Arrays.toString(array));
}
//选择排序算法
public static void selectSort(int[] array){
for (int i = 0; i < array.length -1 ; i++) {
int minIndex = i;
int min = array[i];
for (int j = i+1; j <array.length ; j++) {
if (min > array[j]){
//说明假定的最小值不是最小
min = array[j];//重置min
minIndex = j;//重置最小值下标
}
}
//交换
if (minIndex != i){
array[minIndex] = array[i];
array[i] = min;
}
System.out.println("第"+i+"轮排序的结果是");
System.out.println(Arrays.toString(array));
}
}
}
我们来语言加深一下记忆:
外层循环控制第几轮排序,内层循环是用来控制我们的排序开始的位置
其中,优点在哪?我们发现我们的数据交换的方式跟我们的冒泡排序不一样了,因为这里是一次交换,不像是我们的冒泡排序那样,每次达到要求就交换,所以我们的选择排序,用了最小值下标这个中间辅助变量,用来只发生一次变化
那有人会觉得,若是我第N轮恰好不用交换呢?我们发现我们交换的时候多了一层if判断,这个if判断就是用来判断,当前最小值下标是不是我们一开始假定的最小值的下标,如果不是在交换,是的话就直接输出了,不发生交换,算是一个小优化
然后我们测一测选择排序去排序一个array[80000]数组的时间,我们发现就单单2秒钟或者3秒钟,确实比冒泡排序快多了