選擇排序算法的實現思路類似於插入排序,即已排序區間+未排序區間
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();
}
}
期待留言和分享哦
一起學習,一起進步(笑臉~~~)