挑战七大排序算法-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();
    }
}

期待留言和分享哦

一起学习,一起进步(笑脸~~~)

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