选择排序 —— 排序算法系列

假设我们有如下一个数组:

      

使用选择排序算法对这个数组进行排序,步骤如下:

第 1 次

  • 在下标0到6之间找到最小的数字,我们可以发现最小的数字是15,它在下标为4的位置上;
  • 把下标4上面的数字跟下标0上面的数字互换,得到排序如下图的数组:

      

第 2 次

  • 在下标1到6之间找到最小的数字,我们可以发现最小的数字是33,它在下标为5的位置上;
  • 把下标5上面的数字跟下标1上面的数字互换,得到排序如下图的数组:

      

第 3 次

  • 在下标2到6之间找到最小的数字,我们可以发现最小的数字是48,它在下标为5的位置上;
  • 把下标5上面的数字跟下标2上面的数字互换,得到排序如下图的数组:

      

按照上面的方式进行到第6次,就完成了排序,用 Java 实现的选择排序算法代码如下:

public class SelectionSort {

    public static void main(String[] args){
        int[] arr = new int[]{3,4,1,5,7,6,0,2};
        sort(arr);
        printArr(arr);
    }

    public static void sort(int[] arr){
        int length = arr.length;
        for(int i = 0; i < length;i++){
            int indexOfLastSmall = getIndexOfLastSmall(arr,i);
            if(arr[i] > arr[indexOfLastSmall]){
                swap(arr,i,indexOfLastSmall);
                printArr(arr);
            }
        }
    }

    public static int getIndexOfLastSmall(int[] arr,int start){
        int length = arr.length;
        int smallest = arr[start];
        int indexOfLastSmall = start;
        for(int i = start + 1; i<length;i++){
            if(arr[i] < smallest){
                smallest = arr[i];
                indexOfLastSmall = i;
            }
        }
        return indexOfLastSmall;
    }

    public static void swap(int[] arr, int left,int right){
        int temp = arr[left];
        arr[left] = arr[right];
        arr[right] = temp;
    }

    public static void printArr(int[] arr){
        for(int i=0;i<arr.length;i++){
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }
}

分析:

  在上述的排序过程中,我们可以发现一个规律:为了在 k 个选项中找到最小的数字,我们需要进行 k - 1 次比较。

  假设数组中有 n 个数字:

    1. 第1步,找出这 n 个数字中最小的一个,我们进行了 n - 1 次比较;
    2. 第2步,找出剩余 n - 1 个数字中最小的一个,我们进行了 n - 2 次比较;

    ...依此类推......直到最后一步,在两个数字中找出最小的一个,我们进行了1次比较。

  我们可以设步数为 j,设数组的长度为 n,在每一步的比较中,我们将会在 n - j + 1 个数字里面进行 n - j 次比较,找到这些数字里面最小的数字。

  综上所述,我们可以得到如下的公式:

    排序过程总比较次数 = 1 + 2 + 3 + ... + (n - 1) = (1/2) * n * (n-1) ≈ (1/2) * n2

  从上面的公式可以得知,选择排序算法的时间复杂度为 O(n2),n2 前面的系数并不重要,因为 n2 才是对次数增长起决定性作用的。

  那么,如果进行排序前的数组已经是排好顺序的了,会不会提升排序算法的效率呢?

  答案是否定的。有兴趣的可以动手试试,你会看到不管给出的数组是否有序,选择排序算法都需要一样多的比较次数。

  选择排序属于 "in place" 排序,即就地排序,因为它不需要额外的内存空间。

  

时间: 2024-10-13 16:21:55

选择排序 —— 排序算法系列的相关文章

白话经典算法系列之四 直接选择排序及交换二个数据的正确实现

分类: 白话经典算法系列 2011-08-09 11:15 16682人阅读 评论(29) 收藏 举报 算法面试c 直接选择排序和直接插入排序类似,都将数据分为有序区和无序区,所不同的是直接播放排序是将无序区的第一个元素直接插入到有序区以形成一个更大的有序区,而直接选择排序是从无序区选一个最小的元素直接放到有序区的最后. 设数组为a[0…n-1]. 1.      初始时,数组全为无序区为a[0..n-1].令i=0 2.      在无序区a[i…n-1]中选取一个最小的元素,将其与a[i]交

数据结构与算法系列十三(选择排序)

1.引子 1.1.为什么要学习数据结构与算法? 有人说,数据结构与算法,计算机网络,与操作系统都一样,脱离日常开发,除了面试这辈子可能都用不到呀! 有人说,我是做业务开发的,只要熟练API,熟练框架,熟练各种中间件,写的代码不也能“飞”起来吗? 于是问题来了:为什么还要学习数据结构与算法呢? #理由一: 面试的时候,千万不要被数据结构与算法拖了后腿 #理由二: 你真的愿意做一辈子CRUD Boy吗 #理由三: 不想写出开源框架,中间件的工程师,不是好厨子 1.2.如何系统化学习数据结构与算法?

三白话经典算法系列 Shell排序实现

山是包插入的精髓排序排序.这种方法,也被称为窄增量排序,因为DL.Shell至1959提出命名. 该方法的基本思想是:先将整个待排元素序列切割成若干个子序列(由相隔某个"增量"的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序. 由于直接插入排序在元素基本有序的情况下(接近最好情况),效率是非常高的,因此希尔排序在时间效率上比前两种方法有较大提高. 以n=10的一个数组49, 38, 65, 97

白话经典算法系列之三 希尔排序的实现

分类: 白话经典算法系列 2011-08-08 11:41 47406人阅读 评论(46) 收藏 举报 算法shell优化c 希尔排序的实质就是分组插入排序,该方法又称缩小增量排序,因DL.Shell于1959年提出而得名. 该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的 元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序.因为 直接插入排序在元素基本有序的情况下(接近最好情

排序算法系列——八大排序算法对比分析

本系列最后一篇,综合分析下前面介绍的八种排序算法的效率,以及各自的适用情况. 下面先看看八种排序算法的时间复杂度表格: 图中八种排序被分成了两组,一组时间复杂度为O(n^2),另一组相对高效些. 下面先对第一组O(n^2)的四种排序算法进行对比,分别取数组长度为100,1000,10000,100000四个数量级,各个元素在0-10000000之间随机获取.下面看下结果的分析. 排序算法 长度=100 长度=1000 长度=10000 长度=100000 直接插入排序 535 2,198 135

算法系列15天速成——第一天 七大经典排序【上】

原文:算法系列15天速成--第一天 七大经典排序[上] 今天是开篇,得要吹一下算法,算法就好比程序开发中的利剑,所到之处,刀起头落. 针对现实中的排序问题,算法有七把利剑可以助你马道成功. 首先排序分为四种: 交换排序: 包括冒泡排序,快速排序. 选择排序: 包括直接选择排序,堆排序. 插入排序: 包括直接插入排序,希尔排序. 合并排序: 合并排序. 那么今天我们讲的就是交换排序,我们都知道,C#类库提供的排序是快排,为了让今天玩的有意思点, 我们设计算法来跟类库提供的快排较量较量.争取KO对手

算法系列15天速成——第二天 七大经典排序【中】

原文:算法系列15天速成--第二天 七大经典排序[中] 首先感谢朋友们对第一篇文章的鼎力支持,感动中.......  今天说的是选择排序,包括“直接选择排序”和“堆排序”. 话说上次“冒泡排序”被快排虐了,而且“快排”赢得了内库的重用,众兄弟自然眼红,非要找快排一比高下. 这不今天就来了两兄弟找快排算账. 1.直接选择排序: 先上图: 说实话,直接选择排序最类似于人的本能思想,比如把大小不一的玩具让三岁小毛孩对大小排个序, 那小孩首先会在这么多玩具中找到最小的放在第一位,然后找到次小的放在第二位

(转载)排序算法系列

排序算法系列 目录 概述 概念 排序是计算机内经常进行的一种操作,其目的是将一组"无序"的记录序列调整为"有序"的记录序列. 排序分为内部排序和外部排序. 若整个排序过程不需要访问外存便能完成,则称此类排序问题为内部排序. 反之,若参加排序的记录数量很大,整个序列的排序过程不可能在内存中完成,则称此类排序问题为外部排序. 排序分类 如果按照策略来分类,大致可分为:交换排序.插入排序.选择排序.归并排序和基数排序.如 图-排序策略分类图 所示. 图-排序策略分类图 算

经典排序算法系列7----堆与堆排序

堆排序与快速排序,归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法.学习堆排序前,先讲解下什么是数据结构中的二叉堆. 二叉堆的定义 二叉堆是完全二叉树或者是近似完全二叉树. 二叉堆满足二个特性: 1.父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值. 2.每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆). 当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆.当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆.下图展示一个最小堆: 由于其它几

算法系列笔记1(排序)

本次主要记录一些经典的排序算法,其中包括冒泡排序.直接选择排序.插入排序.归并排序.快速排序.堆排序.希尔排序.桶排序以及计数排序和基数排序.首先会给出这些排序算法的基本思想,然后给出实现的代码,最后会给出其时间复杂度. 1:冒泡排序 思想: (1):比较相邻的前后两个元素,如果后面的数据小于前面的数据,则交换这两个数据的位置.这样经过一次遍历,最小的元素将在第0个位置,属于"冒泡". (2):重复第一步,依次将第二小-的元素排列到数组的顶端. // 交换数据的三种方法 void sw