选择排序算法的实现思路类似于插入排序,即已排序区间+未排序区间
1.算法定义
选择排序是基于选择的排序,即每次需要选择元素进行排序
2.算法思想
(1)第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置
(2)然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。
(3)以此类推,直到全部待排序的数据元素的个数为零
来看看,选择排序原理示意图
3.代码实现
(1)首先来看一下,找最小元素的选择排序实现
有序区间+无序区间
关于有序区间和无序区间的边界问题,可以画个图自己分析一下(这块很不容易理解哦,建议画图)
//将未排序区间的最小值放到以排序区间的末尾
public static void selectSort(int[] array){
int n = array.length;
if(n <= 1){
return;
}else{
//有序区间:[0,i)无序区间:[i,n)
for(int i = 0;i < n-1;i++){
int minValueIndex = i;
//j = [有序区间后一个元素,无序区间的最后一个元素]
for(int j = i+1;j < n;j++){
if(array[j] < array[minValueIndex]) {
minValueIndex = j;
}
}
//交换
int temp = array[i];
array[i] = array[minValueIndex];
array[minValueIndex] = temp;
}
}
}
那看看我的图吧:i是从0开始遍历的,那么在刚开始时,有序区间为[0,i],那么无序区间就是[i,n).哈哈哈,其实理解起来也还好
(2)接下来,这个我可是看了好久,每次找最大元素放到最后
无序区间+有序区间
刚开始,i = 0,整个数组数据都为无序区间里的元素,所以呢,无序区间为[0,n-i),有序区间为[n-i,n)
//每次取最大值放到无序区间的最后
public static void selectSort0(int[] array){
int n = array.length;
if (n <= 1){
return;
}else{
for(int i = 0;i < n-1;i++){
//无序区间:[0,n-i)有序区间:[n-i,n)
int j = 1;//j = [无序区间的第二个元素,有序区间的前一个元素]
int maxValueIndex = 0;
for(;j < n-i;j++){
if(array[j] > array[maxValueIndex]){
maxValueIndex = j;
}
}
//交换
int temp = array[n-i-1];
array[n-i-1] = array[maxValueIndex];
array[maxValueIndex] = temp;
}
}
}
4.看个栗子
来测试一个数组a={2,5,1,7,3,6,9}
public static void main(String[] args) {
int[] a = {2,5,1,7,3,6,9};
//有序区间+无序区间
int[] b = a.clone();
selectSort(b);
System.out.println(Arrays.toString(b));
//无序区间+有序区间
int[] c = a.clone();
selectSort0(c);
System.out.println(Arrays.toString(c));
//通过Arrays.sort进行验证排序结果
int[] d = a.clone();
Arrays.sort(d);
System.out.println(Arrays.toString(d));
System.out.println(Arrays.equals(b,d));
System.out.println(Arrays.equals(c,d));
}
测试结果:
下面,按照国际惯例,嗯嗯,就是测一下100000个数据元素的排序速度,
比起希尔排序,插入排序会慢一点,不过没关系,他也有他特殊的使用场景
测试时间代码在这里呀
public static void testSpeed(){
Random random = new Random(20191019);
int[] a = new int[100000];
int[] b = a.clone();
for (int i = 0;i < 100000;i++){
a[i] = random.nextInt(200000);
}
long begin = System.nanoTime();
selectSort(a);
long end = System.nanoTime();
double s = (end-begin)/1000/1000/1000;
System.out.printf("selectSort:一共耗时:%.5f 秒%n",s);
long begin0 = System.nanoTime();
selectSort0(a);
long end0 = System.nanoTime();
double s0 = (end-begin)/1000/1000/1000;
System.out.printf("selectSort0:一共耗时:%.5f 秒%n",s);
}
5.算法分析(复杂度、稳定性)
1.复杂度分析
时间复杂度:(两个循环)
最好情况:O(n^2)
最坏情况:O(n^2)
平均情况:O(n^2)
空间复杂度:O(1)(因为没有开辟新空间)-原地排序算法
2.稳定性分析
不稳定的排序算法
比如5,8,5,2,9这样一组数组,使用选择排序算法来看,两个5原来的顺序在排序结束后被改变了,所以选择排序算法是不稳定的。
6.源程序
package sort.selectSort;
import java.util.Arrays;
import java.util.Random;
/**
* @Author:Star
* @Date:Created in 11:05 2019/10/19
* @Description:选择排序
* 时间复杂度:
* 空间复杂度:
* 稳定性:
*/
public class Sort {
//将未排序区间的最小值放到以排序区间的末尾
public static void selectSort(int[] array){
int n = array.length;
if(n <= 1){
return;
}else{
//有序区间:[0,i)无序区间:[i,n)
for(int i = 0;i < n-1;i++){
int minValueIndex = i;
//j = [有序区间后一个元素,无序区间的最后一个元素]
for(int j = i+1;j < n;j++){
if(array[j] < array[minValueIndex]) {
minValueIndex = j;
}
}
//交换
int temp = array[i];
array[i] = array[minValueIndex];
array[minValueIndex] = temp;
}
}
}
//每次取最大值放到无序区间的最后
public static void selectSort0(int[] array){
int n = array.length;
if (n <= 1){
return;
}else{
for(int i = 0;i < n-1;i++){
//无序区间:[0,n-i)有序区间:[n-i,n]
int j = 1;//j = [无序区间的第二个元素,有序区间的前一个元素]
int maxValueIndex = 0;
for(;j < n-i;j++){
if(array[j] > array[maxValueIndex]){
maxValueIndex = j;
}
}
//交换
int temp = array[n-i-1];
array[n-i-1] = array[maxValueIndex];
array[maxValueIndex] = temp;
}
}
}
public static void testSpeed(){
Random random = new Random(20191019);
int[] a = new int[100000];
int[] b = a.clone();
for (int i = 0;i < 100000;i++){
a[i] = random.nextInt(200000);
}
long begin = System.nanoTime();
selectSort(a);
long end = System.nanoTime();
double s = (end-begin)/1000/1000/1000;
System.out.printf("selectSort:一共耗时:%.5f 秒%n",s);
long begin0 = System.nanoTime();
selectSort0(a);
long end0 = System.nanoTime();
double s0 = (end-begin)/1000/1000/1000;
System.out.printf("selectSort0:一共耗时:%.5f 秒%n",s);
}
public static void main(String[] args) {
/*
int[] a = {2,5,1,7,3,6,9};
//有序区间+无序区间
int[] b = a.clone();
selectSort(b);
System.out.println(Arrays.toString(b));
//无序区间+有序区间
int[] c = a.clone();
selectSort0(c);
System.out.println(Arrays.toString(c));
//通过Arrays.sort进行验证排序结果
int[] d = a.clone();
Arrays.sort(d);
System.out.println(Arrays.toString(d));
System.out.println(Arrays.equals(b,d));
System.out.println(Arrays.equals(c,d));*/
testSpeed();
}
}
期待留言和分享哦
一起学习,一起进步(笑脸~~~)