排序算法 - 选择排序算法过程及耗时比较

选择排序算法

选择排序算法是一种不稳定的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素存放在序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到全部待排序的数据元素排完

在这里插入图片描述


Java实现选择排序过程

先一步一步的实现:

设置一个minIndex表示最小数的索引
min表示最小的数

每一趟遍历都重新假设最开始的数为最小数

package com.company.sort;

import java.util.Arrays;

/**
 * @author zfk
 * 选择排序
 */
public class SelectSort {

    public static void main(String[] args) {
        int[] arr = {2,8,-1,10,-5};
        selectSort(arr);
    }

    public static void selectSort(int[] arr){
        //最小的数的索引,假设下标为0的arr[0]为最小的数
        int minIndex = 0;
        int min = arr[minIndex];

        //第一轮比较
        for (int j = 0+1;j < arr.length;j++){
            //如果存在比min小的数,获得该最小值的值与位置
            if (min > arr[j]){
                minIndex = j;
                min = arr[minIndex];
            }
        }
        //把arr[0]放到最小值所在位置,将最小值min放在arr[0]
        //即数组最小值与arr[0]交换位置
        arr[minIndex] = arr[0];
        arr[0] = min;
        System.out.println("第一轮交换:"+ Arrays.toString(arr));


        //第二轮比较
        minIndex = 1;
        min = arr[minIndex];
        for (int j = 0+2;j < arr.length;j++){
            //如果存在比min小的数,获得该最小值的值与位置
            if (min > arr[j]){
                minIndex = j;
                min = arr[minIndex];
            }
        }
        //把arr[0]放到最小值所在位置,将最小值min放在arr[0]
        //即数组最小值与arr[0]交换位置
        arr[minIndex] = arr[1];
        arr[1] = min;
        System.out.println("第二轮交换:"+ Arrays.toString(arr));

        //第三轮比较
        minIndex = 2;
        min = arr[minIndex];
        for (int j = 0+3;j < arr.length;j++){
            //如果存在比min小的数,获得该最小值的值与位置
            if (min > arr[j]){
                minIndex = j;
                min = arr[minIndex];
            }
        }
        //把arr[0]放到最小值所在位置,将最小值min放在arr[0]
        //即数组最小值与arr[0]交换位置
        arr[minIndex] = arr[2];
        arr[2] = min;
        System.out.println("第三轮交换:"+ Arrays.toString(arr));

        //第四轮比较
        minIndex = 3;
        min = arr[minIndex];
        for (int j = 0+4;j < arr.length;j++){
            //如果存在比min小的数,获得该最小值的值与位置
            if (min > arr[j]){
                minIndex = j;
                min = arr[minIndex];
            }
        }
        //把arr[0]放到最小值所在位置,将最小值min放在arr[0]
        //即数组最小值与arr[0]交换位置
        arr[minIndex] = arr[3];
        arr[3] = min;
        System.out.println("第四轮交换:"+ Arrays.toString(arr));

    }
}

在这里插入图片描述

我们可以发现规律:

  • 每次遍历假设最小的数在最开始的位置
  • 每次遍历都排除上一次遍历的最小值

就可以用两个for循环简化上面的代码:

package com.company.sort;

import java.util.Arrays;

/**
 * @author zfk
 * 选择排序
 */
public class SelectSort {

    public static void main(String[] args) {
        int[] arr = {2,8,-1,10,-5};
        selectSort(arr);
    }

    public static void selectSort(int[] arr){
        //最小的数的索引,假设下标为0的arr[0]为最小的数

        for (int i = 0;i < arr.length -1;i++) {
            int minIndex = i;
            int min = arr[minIndex];

            for (int j = i; j < arr.length; j++) {
                //如果存在比min小的数,获得该最小值的值与位置
                if (min > arr[j]) {
                    minIndex = j;
                    min = arr[minIndex];
                }
            }
            //把arr[0]放到最小值所在位置,将最小值min放在arr[0]
            //即数组最小值与arr[0]交换位置
            //如果最开始的位置即是最小值,就不执行交换
            if (minIndex != i) {
                arr[minIndex] = arr[i];
                arr[i] = min;
            }
            System.out.println("第"+(i+1)+"轮交换:" + Arrays.toString(arr));
        }

    }
}


选择排序算法与冒泡排序

因为选择排序算法是两个for循环,所以可以说选择排序算法的时间复杂度为O(n^2)

我们来测试一下排序8000个0~80000的数据所需时间

    public static void main(String[] args) {
        int[] arr = new int[8000];
        for(int i = 0 ;i <arr.length;i++){
            //随机生成80000内的整数
            arr[i] = (int) (Math.random()*80000);
        }
        Date dataBefore = new Date();

        selectSort(arr);

        Date dateAfter = new Date();

        System.out.println("消耗了:"+(dateAfter.getTime()-dataBefore.getTime())+"ms");

    }

在这里插入图片描述

前面的冒泡排序
在这里插入图片描述

时间差距挺大的,分析一下两者时间复杂度同时O(n^2),为什么差距挺大?
甚至,如果设置80000个数据,差距会更大

选择排序的时间主要花费在遍历上,它每次遍历仅交换一个数据(甚至不交换),而冒泡排序,每次遍历可能会交换多次,但是好在可以减少遍历次数

同是O(n^2)的时间复杂度的算法,相差也挺大的


不稳定性

什么是不稳定性:就是两个相同元素在排序前后,前后位置顺序是否相同,不相同就是不稳定

很明显选择排序算法是不稳定的排序算法
我们可以修改一下前面的程序来验证:

package com.company.sort;

import java.util.Arrays;
import java.util.Date;

/**
 * @author zfk
 * 选择排序
 */
public class SelectSort {

    public static void main(String[] args) {

        int[] arr = {2,2,1};
        selectSort(arr);


    }

    public static void selectSort(int[] arr){
        //最小的数的索引,假设下标为0的arr[0]为最小的数

        for (int i = 0;i < arr.length -1;i++) {
            int minIndex = i;
            int min = arr[minIndex];

            for (int j = i; j < arr.length; j++) {
                //如果存在比min小的数,获得该最小值的值与位置
                if (min > arr[j]) {
                    minIndex = j;
                    min = arr[minIndex];
                }
            }
            //把arr[0]放到最小值所在位置,将最小值min放在arr[0]
            //即数组最小值与arr[0]交换位置
            //如果最开始的位置即是最小值,就不执行交换
            if (minIndex != i) {
                arr[minIndex] = arr[i];
                arr[i] = min;
                System.out.println(i+"位置交换了"+minIndex+"位置");
            }
            System.out.println("第"+(i+1)+"轮交换:" + Arrays.toString(arr));
        }

    }
}

在这里插入图片描述

曾经数组{2,2,1},第一个2在第二个2前,选择排序后,第一个2在第二个2后,与1交换了位置

这就是不稳定性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值