作者前言
大家好,我是阿濠,今篇内容跟大家分享的是排序算法之选择排序,很高兴分享到segmentfault与大家一起学习交流,初次见面请大家多多关照,一起学习进步.
一、选择排序的介绍
基本介绍
选择式排序也属于内部排序法
,是从欲排序的数据
中,按指定的规则选出某一元素
,再依规定交换位置
后达到排序的目的
。
排序思想
1.第1次从arr[0] ~ arr[n-1]中选取最小值
,与arr[0]交换
2.第2次从arr[1] ~ aarr[n-1]中选取最小值
,与arr[1J交换
3.第3次从arr[2] ~ arr[n-1]中选取最小值
,与arr[2]交换
4.第i次从arr[i-1] ~ arr[n-1]中选取最小值
,与arr[i-1]交换
5.第n-1次从arr[n-2] ~ arr[n-1]中选取最小值
,与arr[n-2] 交换
总共通过n-1次,得到一个按排序码从小到大排列的有序序列。
二、通过应用示例认识选择排序
由一群牛,颜值分别是: 100,34,119,1
使用选择排序法
将其排成一个从小到大的有序数列。
步骤思路:
1.需要进行数组大小-1的循环
2.每次循环
定义当前数是最小数
,与后面数比较
,若更小
则确定最小数
并得到下标进行交换
//使用逐步推导的方式来,讲解选择排序
//第1轮
//原始的数组:101, 34, 119, 1
//第一轮排序: 1, 34, 119,101
//算法先简单-->再复杂
//就是可以把一个复杂的算法,拆分成简单的问题-》逐步解决
int minIndex = 0;//最小值下标
int min = arr[0];//最小值为当前第一个数
for(int j = 0 + 1; j < arr.length; j++){
//若最小值比其他还大,则说明不是最小值
if (min > arr[j]) {
min = arr[j];
minIndex = j;
}
}
if(minIndex!=0){
//将当前最小值与之前最小值进行交换
arr[minIndex] = arr[0];
arr[0] = min;
}
System.out.println("第一轮交换后");
System.out.println(Arrays.toString(arr));
运行结果如下:
排序前:[101, 34, 119, 1]
第一轮交换后:[1, 34, 119, 101]
//第二轮
minIndex = 1;//最小值下标
min = arr[1];//最小值为当前第一个数
for(int j = 1 + 1; j < arr.length; j++){
//若最小值比其他还大,则说明不是最小值
if (min > arr[j]) {
min = arr[j];
minIndex = j;
}
}
if(minIndex!=1){
//将当前最小值与之前最小值进行交换
arr[minIndex] = arr[1];
arr[1] = min;
}
System.out.println("第二轮交换后");
System.out.println(Arrays.toString(arr));
运行结果如下:
第一轮交换后:[1, 34, 119, 101]
第二轮交换后:[1, 34, 119, 101]
//第三轮
minIndex = 2;//最小值下标
min = arr[2];//最小值为当前第一个数
for(int j = 2 + 1; j < arr.length; j++){
//若最小值比其他还大,则说明不是最小值
if (min > arr[j]) {
min = arr[j];
minIndex = j;
}
}
if(minIndex!=2){
//将当前最小值与之前最小值进行交换
arr[minIndex] = arr[2];
arr[2] = min;
}
System.out.println("第三轮交换后");
System.out.println(Arrays.toString(arr));
运行结果如下:
第一轮交换后:[1,34,119,101]
第二轮交换后:[1,34,119,101]
第三轮交换后:[1,34,101,119]
规律已经出来了,最小值、判断交换
是相似
,改变的是每次最小值的下标
,即进行如下代码抽整:
//时间复杂度是O(n^2)
for (int i=0 ;i<arr.length;i++){
int minIndex = i;//最小值下标
int min = arr[i];//最小值为当前第一个数
for(int j = i + 1; j < arr.length; j++){
//若最小值比其他还大,则说明不是最小值
if (min > arr[j]) {
min = arr[j];
minIndex = j;
}
}
if(minIndex != i){
//将当前最小值与之前最小值进行交换
arr[minIndex] = arr[i];
arr[i] = min;
}
System.out.println("第"+(i+1)+"轮交换后");
System.out.println(Arrays.toString(arr));
}
//运行结果如下:
//排序前:[101, 34, 119, 1]
排序后
第1轮交换后:[1, 34, 119, 101]
第2轮交换后:[1, 34, 119, 101]
第3轮交换后:[1, 34, 101, 119]
第4轮交换后:[1, 34, 101, 119]
三、复杂度分析
选择排序的交换操作介于0和(n-1)次之间
。
选择排序的比较操作为n(n-1)/2次之间
。
选择排序的赋值操作介于0和3(n-1)次之间
。
比较次数O(n^2)
,比较次数与关键字
的初始状态无关
,总的比较次数N=(n-1)+(n-2)+...+1=n*(n-1)/2
。
交换次数O(n)
,最好情况是,已经有序交换0次
;最坏情况是,逆序交换n-1次
。
交换次数比冒泡排序少多了,由于交换所需CPU时间比比较所需的CPU时间多,n值较小时,选择排序比冒泡排序快
。