美文网首页
选择排序(Selection Sort)

选择排序(Selection Sort)

作者: 小波同学 | 来源:发表于2021-11-19 00:42 被阅读0次

    一、算法概述

    1.1 算法分类

    十种常见排序算法可以分为两大类:

    • 比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。

    • 非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。

    1.2 算法复杂度

    1.3 相关概念

    • 稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。
    • 不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。
    • 时间复杂度:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。
    • 空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数。

    二、选择排序(Selection Sort)

    选择排序(Selection-sort)是一种简单直观的排序算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

    2.1 算法描述

    n个记录的直接选择排序可经过n-1趟直接选择排序得到有序结果。具体算法描述如下:

    • 初始状态:无序区为R[1..n],有序区为空;
    • 第i趟排序(i=1,2,3…n-1)开始时,当前有序区和无序区分别为R[1..i-1]和R(i..n)。该趟排序从当前无序区中-选出关键字最小的记录 R[k],将它与无序区的第1个记录R交换,使R[1..i]和R[i+1..n)分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区;
    • n-1趟结束,数组有序化了。

    2.2 动图演示

    Selection Sort

    2.3 排序过程

    下面以数列{20,40,30,10,60,50}为例,演示它的选择排序过程(如下图)。


    排序流程

    • 第1趟:i=0。找出a[1...5]中的最小值a[3]=10,然后将a[0]和a[3]互换。 数列变化:20,40,30,10,60,50 -- > 10,40,30,20,60,50
    • 第2趟:i=1。找出a[2...5]中的最小值a[3]=20,然后将a[1]和a[3]互换。 数列变化:10,40,30,20,60,50 -- > 10,20,30,40,60,50
    • 第3趟:i=2。找出a[3...5]中的最小值,由于该最小值大于a[2],该趟不做任何处理。
    • 第4趟:i=3。找出a[4...5]中的最小值,由于该最小值大于a[3],该趟不做任何处理。
    • 第5趟:i=4。交换a[4]和a[5]的数据。 数列变化:10,20,30,40,60,50 -- > 10,20,30,40,50,60

    2.4 代码实现

    /**
     * @author: huangyibo
     * @Date: 2021/11/17 16:17
     * @Description: 选择排序
     * 文字描述(以升序为例)
     * 1、将数组分为两个子集, 排序的和未排序的, 每一轮从未排序的子集中选出最小的元素, 放入排序子集
     * 2、重复以上步骤, 直到整个数组有序
     *
     * 优化方式:
     * 1、为减少交换次数, 每一轮可以先找最小的索引, 在每一轮最后交换元素
     *
     * 与冒泡排序比较:
     * 1、二者平均时间复杂度都是O(n²)
     * 2、选择排序一般都要快于冒泡, 因为其交换次数少
     * 3、但如果集合有序度高, 冒泡优于选择
     * 4、冒泡属于稳定排序算法, 而选择属于不稳定排序算法
     */
    public class SelectionSort {
    
        public static void main(String[] args) {
            int[] arr = {5, 9, 7, 4, 1, 3, 2, 8};
    
            selectionSort(arr);
            System.out.println(Arrays.toString(arr));
        }
    
        public static void selectionSort(int[] arr) {
            //i代表每轮选择最小元素要交换到的目标索引
            for (int i = 0; i < arr.length - 1; i++) {
                //代表最小元素的索引
                int minIndex = i;
                for (int j = minIndex + 1; j < arr.length; j++) {
                    if(arr[minIndex] > arr[j]){
                        minIndex = j;
                    }
                }
                //在每一轮最后交换元素
                if(minIndex != i){
                    swap(arr, i, minIndex);
                }
            }
        }
    
        public static void swap(int[] arr, int i, int j) {
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    }
    

    2.5 算法分析

    表现最稳定的排序算法之一,因为无论什么数据进去都是O(n²)的时间复杂度,所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧。理论上讲,选择排序可能也是平时排序一般人想到的最多的排序方法了吧。

    2.6 与冒泡排序比较

    • 1、二者平均时间复杂度都是O(n²)
    • 2、选择排序一般都要快于冒泡, 因为其交换次数少
    • 3、但如果集合有序度高, 冒泡优于选择
    • 4、冒泡属于稳定排序算法, 而选择属于不稳定排序算法

    参考:
    https://www.cnblogs.com/onepixel/articles/7674659.html

    https://www.cnblogs.com/skywang12345/p/3597641.html

    相关文章

      网友评论

          本文标题:选择排序(Selection Sort)

          本文链接:https://www.haomeiwen.com/subject/gyfjtrtx.html