挑戰七大排序算法-03選擇排序

選擇排序算法的實現思路類似於插入排序,即已排序區間+未排序區間

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();
    }
}

期待留言和分享哦

一起學習,一起進步(笑臉~~~)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章