1. 基本思想

选择排序(Select Sort)同样是最基础的排序算法之一,它的核心思想是:将要排序的序列分成有序和无序两个部分,开始时有序部分为空,然后经过 n - 1 次遍历,每次遍历都在无序部分选取一个最值元素,然后放在有序部分中,到所有遍历完成时有序部分已经扩展到整个区间了,即排序完成。

为了让大家对选择排序有更加清晰的认识,我们以下面这组数据作为例子来对选择排序进行演示:

现在,我们需要对包含 8 个元素的序列 [1, 9, 2, 6, 0, 8, 1, 7] 进行升序(从小到大)排序。

按照选择排序的思想,我们需要在序列的无序部分用某种手段去选出最值元素,我们在简单选择排序中通常用的都是顺序查找法,然后将找到的最值元素通过交换,放到无须部分的边界位置(靠近有序部分的那边),实现有序部分的扩充。下面就是选择排序的过程:

第一趟查找下来,0 作为无序部分的的最小元素被顺序查找选择到,然后交换到无序部分的边界位置,形成了有序部分的第一个元素。

我们下面接着第二查找:

走完第二趟之后,我们可以看到 1 作为无序部分中的最小元素被交换到了无序部分的最右侧,形成了已排序区间的第二个元素。

其实看到这里,大家都应该明白了,我们只要多再进行 7−27 - 27−2 趟查找,就能将有序部分扩大到整个序列,完成选择排序的过程,使得序列中所有的元素都是有序的。如果你还不懂这种思想的话,我#¥%&…

2. 代码实现

选择排序的代码实现同样非常好理解,在两层 for 循环中,外层循环控制有序部分的右边界,内层循环控制顺序查找区间的范围,if 条件句用于更新查找的最值,在完成一次查找后,还要将找到的值交换到边界位置。实现代码如下:


public void selectSort(int[] arr, int n) {for (int i = 0; i < n - 1; i++) {int min = i; // #1 最小值元素的下标for (int j = i + 1; j < n; j++) {if (arr[min] > arr[j]) {min = j; // #2 更新最小值的小标}}// #3 将最值元素交换到有序部分if (min != i) {int temp = arr[min];arr[min] = arr[i];arr[i] = temp;}}
}

当然,简单选择排序的写法肯定不止一种,下面还有一种锁定下标的写法,但是这种写法没有上面那种能明显体现选择排序的思想,而且容易被人误认为是冒泡排序……

public void selectSort(int[] arr, int n) {// #1 要有序部分要拓展的位置for (int i = 0; i < n - 1; i++) {// #2 无序部分的范围for (int j = i + 1; j < n; j++) {// #3 注意比较的下标值(区分冒泡排序)if (arr[i] > arr[j]) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}}
}

我们可以从上面代码得出,选择排序的时间复杂度比较稳定,在最好和最坏情况都是O(n2)O(n^2)O(n2)。

在稳定性方面,像对这组数据[4, 6, 4, 1, 7]进行选择排序的时候,会改变两个 4 在排序前的相对前后顺序。由此可知,选择排序是一种不稳定的排序。

3. 优化

上面说到的选择排序是简单选择排序,它的间复杂度是 O(n2)O(n^2)O(n2)。如果让你对选择排序进行优化,你会怎么做?我们不妨从选择的方式来考虑,上面的选择方式用的是普通的顺序查找,我们需要想到比这个更快的。

优化方式1:双指针法

我们可以在一次顺序查找中,用两个指针分别去寻找最大值和最小值,然后从有序部分从两边向中间拓展。虽然最终算法时间复杂度不变,但是确实是可以减少一半的比较的。下图是一次选择过程,可以理解一下。

注意:这种思想是没有问题,但是因为有最大和最小两个值,在后面在调换的时候,可能因为你写的代码处理不当而出现问题。

优化方式2:二分法

我们都知道,二分查找只能在有序的序列中使用,那么我们应该如何用上二分的思想呢?没错,就是用二叉树!能满足快速查找最值元素,而且最值元素被交换后的维护成本又相对比较低就只有堆了。

诶,这不就变成堆排序了吗?是的,事实上堆排序也是选择排序的一种,而且的它的效率很高,是为数不多的时间复杂度为 O(nlogn)O(nlogn)O(nlogn) 的排序算法之一。我们迟点也会介绍堆排序,这里就不多说了。


又顺手更了一波,别忘了点赞哦~

图解排序算法之谈「选择排序」相关推荐

  1. 【简单排序算法】:简单选择排序、直接插入排序和冒泡排序

    [简单排序算法]:简单选择排序.直接插入排序和冒泡排序 简单选择排序: 原理:设所排序序列的记录个数为n.i取1,2,-,n-1,每次从所有n-i+1个记录(Ri,Ri+1,-,Rn)中找出最小的记录 ...

  2. C语言排序算法(一)——选择排序实现

    C语言排序算法(一)--选择排序实现 编写程序,实现从键盘输入10个数,并用选择法从小到大排序. 简单选择排序的基本思想:第1趟,在待排序记录r[1]r[n]中选出最小的记录,将它与r[1]交换:第2 ...

  3. 加标志量的选择排序算法c语言,置换选择排序算法详解(C语言实现)

    上一节介绍了增加 k-路归并排序中的 k 值来提高外部排序效率的方法,而除此之外,还有另外一条路可走,即减少初始归并段的个数,也就是本章第一节中提到的减小 m 的值. m 的求值方法为:m=⌈n/l⌉ ...

  4. [ 数据结构 -- 手撕排序算法第四篇 ] 选择排序

    手撕排序算法系列之第四篇:选择排序. 从本篇文章开始,我会介绍并分析常见的几种排序,大致包括直接插入排序,冒泡排序,希尔排序,选择排序,堆排序,快速排序,归并排序等. 大家可以点击此链接阅读其他排序算 ...

  5. 浅谈排序算法:冒泡排序法和选择排序法的区别

    之前学习了冒泡排序法和选择排序法,最近被老师问某个道题用的是什么排序法.自己居然答不出来,才发现自己没有真正弄懂,这两个算法的原理和区别,所以····· 1冒泡排序法 1.1什么是冒泡排序法? 顾名思 ...

  6. 基础排序算法(冒泡排序,选择排序,插入排序)

    最近经常调用api中的排序算法,很少自己写了,有时候也只写写快速排序这些比较快的排序,然而刚开始学排序时用的一些基本的排序算法却有点忘了 正好今天Java老师让我们每个人写个选择排序热热手,趁这个机会 ...

  7. python遍历数组冒泡排序_经典排序算法(冒泡排序,选择排序,插入排序,快速排序,堆排序)python实现...

    最近在复习经典排序算法,自己用python也实现了一下,这里不会涉及到原理(因为网上方法已经很详细啦),就把函数贴上来,可以让大家自己试着运行下,再结合别处的原理也可以更好地理解它们的实现. 如果有错 ...

  8. java 排序_Java中常见的排序算法有哪些?---选择排序

    排序相关的的基本概念 排序: 将一组杂乱无章的数据按一定的规律顺次排列起来. 数据表( data list): 它是待排序数据对象的有限集合. 排序码(key):通常数据对象有多个属性域, 即多个数据 ...

  9. java中queue排序_Java中常见的排序算法有哪些?---选择排序

    排序相关的的基本概念 排序: 将一组杂乱无章的数据按一定的规律顺次排列起来. 数据表( data list): 它是待排序数据对象的有限集合. 排序码(key):通常数据对象有多个属性域, 即多个数据 ...

最新文章

  1. c++经典书籍--c++ primer 第6版
  2. 语音识别真的比肩人类了?听听阿里iDST初敏怎么说
  3. linux 版本的scipy,linux安装scipy
  4. python写日志到文件_Python日志文件没有正确地写入日志消息,只有格式
  5. 全民 Transformer (一): Attention 在深度学习中是如何发挥作用的
  6. ORACLE VARCHAR2
  7. 【PAT B1019/A1069】数字黑洞
  8. 尚硅谷大数据—搭建Hadoop集群—硬件环境准备
  9. 库存商品计算成本的几种方法
  10. wpa_supplicant2.9编译过程
  11. 技术团队如何高效开会
  12. Guava的两种本地缓存策略
  13. [汉化主题] Knowhow v1.1.16 – 响应式论坛知识库WordPress主题
  14. 虚拟机与主机ssh连接
  15. Ruby On Rails的傻瓜安装
  16. flv视频转换成mp4格式怎么转?
  17. 【图像配准】基于灰度的模板匹配算法(三):划分强度一致法(PIU)
  18. phython 错题
  19. XP系统meta工具补丁
  20. 一周搞定数电复习//2021-2-2

热门文章

  1. 01-How to setup SDK and compile TAs
  2. 图片爬取数据解析数据持久化
  3. (6)段描述符D/B位
  4. 2020-12-18(何种情况下编译器会提供默认构造函数)
  5. 1.19 String、StringBuffer和StringBuilder类的区别
  6. python实现肯德基店铺查询
  7. html实战例子: 课程表
  8. 计算机网络一些重要的知识
  9. C++之多重继承引发的重复调用
  10. access无法 dolby_如何解决windows 8无法开启杜比音效的问题