算法一看就懂之「 选择排序 」

作者: 奎哥 2020-03-27 09:06:54

「 选择排序 」虽然在实际应用中没有「 插入排序 」广泛,但它也是我们学习排序算法中必不可少的一种。「 冒泡排序 」和「 插入排序 」都是在两层嵌套循环中慢慢比较元素,不停的调整元素的位置。而「 选择排序 」就比较直接了,属于不出手则已,一出手,相应的元素就必须要到位,元素的位置就不会再变了。

下面我们来详细了解下一下它的逻辑。

一、「 选择排序 」是什么?

选择排序 也是一种很简单的排序算法,它的思路也是将一组待排序的数据,分成2段,一段是“已排序”了的数据,另一段是“未排序”的数据。当然,在最开始的时候,“已排序”区段里是没有数据的。排序开始后,每次都从“未排序”的数据中取出一个最小的元素(注意,这里是取最小的元素,这一点与「 插入排序 」是不同的),然后将这个最小的元素插入到“已排序”数据中末尾元素的后面(这里其实是将这个最小元素与“已排序”数据的末尾紧邻的下一位元素进行交换),这样保持了“已排序”中的数据永远是有序的。一直这么循环的去处理,直到所有的“未排序”的数据都已交换完,则整个排序全部完成。

下面用图示例讲解一下:

(图片来源网络)

从上图可以看到,初始数组是

元素 29 72 98 13 87 66 52 51 36
下标 0 1 2 3 4 5 6 7 8
 

要对这个数组进行从小到大排序,默认初始状态是全部无序的,因此对这个数组开始遍历找最小元素。

1.第一遍大循环时,在整个数组中找到最小元素“13”,将这个最小元素“13”与数组的开头位置元素“29”进行交换。交换后数组为:

元素 13 72 98 29 87 66 52 51 36
下标 0 1 2 3 4 5 6 7 8

2.第二遍大循环时,元素“13”属于“已排序”区段了,剩下所有元素都属于“未排序”的区段。从剩下元素中找到最小元素“29”,将这个最小元素“29”与元素“72”进行交换(因为元素“72”是已排序数组紧邻的后一位元素),交换后数组为:

元素 13 29 98 72 87 66 52 51 36
下标 0 1 2 3 4 5 6 7 8

3.第三遍大循环时,“已排序”区段里已经有元素“13”、“29”了,剩下其它元素都属于“未排序”的。从剩下元素中找到最小元素“36”,将这个最小元素“36”与元素“98”进行交换(因为元素“98”是已排序数组紧邻的后一位元素),交换后数组为:

元素 13 29 36 72 87 66 52 51 98
下标 0 1 2 3 4 5 6 7 8

4.第四遍大循环时,“已排序”区段里已经有元素“13”、“29”、“36”了,剩下其它元素都属于“未排序”的。从剩下元素中找到最小元素“51”,将这个最小元素“51”与元素“72”进行交换(因为元素“72”是已排序数组紧邻的后一位元素),交换后数组为:

元素 13 29 36 51 87 66 52 72 98
下标 0 1 2 3 4 5 6 7 8

5.第五遍大循环时,“已排序”区段里已经有元素“13”、“29”、“36”、“51”了,剩下其它元素都属于“未排序”的。从剩下元素中找到最小元素“52”,将这个最小元素“52”与元素“87”进行交换(因为元素“87”是已排序数组紧邻的后一位元素),交换后数组为:

元素 13 29 36 51 52 66 87 72 98
下标 0 1 2 3 4 5 6 7 8

6.第六遍大循环时,“已排序”区段里已经有元素“13”、“29”、“36”、“51”、“52”了,剩下其它元素都属于“未排序”的。从剩下元素中找到最小元素“66”,发现这个最小元素“66”已经是位于已排序数组紧邻的后一位元素了,因此无需交换,数组保持不变:

元素 13 29 36 51 52 66 87 72 98
下标 0 1 2 3 4 5 6 7 8

7.第七遍大循环时,“已排序”区段里已经有元素“13”、“29”、“36”、“51”、“52”、“66”了,剩下其它元素都属于“未排序”的。从剩下元素中找到最小元素“72”,将这个最小元素“72”与元素“87”进行交换(因为元素“87”是已排序数组紧邻的后一位元素),交换后数组为:

元素 13 29 36 51 52 66 72 87 98
下标 0 1 2 3 4 5 6 7 8

8.第八遍大循环时,“已排序”区段里已经有元素“13”、“29”、“36”、“51”、“52”、“66”、“72”了,剩下其它元素都属于“未排序”的。从剩下元素中找到最小元素“87”,发现这个最小元素“87”已经是位于已排序数组紧邻的后一位元素了,因此无需交换,数组保持不变:

元素 13 29 36 51 52 66 72 87 98
下标 0 1 2 3 4 5 6 7 8

9.第九遍大循环时,“已排序”区段里已经有元素“13”、“29”、“36”、“51”、“52”、“66”、“72”、“87”了,剩下未排序的元素只有“98”这一个了,直接保持其位置不变即可,即,此时全部排序完成,数组最终状态为:

元素 13 29 36 51 52 66 72 87 98
下标 0 1 2 3 4 5 6 7 8

下面我们来看一个选择排序的代码示意:

算法题:对数组arr进行从小到大的排序,假设数组arr不为空,arr的长度为n思路:采用选择排序方法

  1. public void selectionSort(int[] arr){ 
  2.     int i,j; 
  3.     int n = arr.length; 
  4.      
  5.     //每一次大循环都能找出剩余元素的最小值 
  6.     for(i=0; i<n; i++){ 
  7.         //min变量是用于存放最小值的下标的,在刚开始的时候,假设位置i是最小值,初始时将i赋值给min 
  8.         int min = i; 
  9.         //子循环是用于比较大小,从i的后面一位开始遍历,遍历后面所有元素 
  10.         for(j=i+1; j<n; j++){ 
  11.             //如果有元素小于min位的值,则将此元素的下标赋值给min 
  12.             if(arr[j] < arr[min]){ 
  13.                 min = j; 
  14.             } 
  15.         } 
  16.         //如果min不等于i,说明刚在在子循环里,找到了最小值,则需要交换元素位置 
  17.         if(min!=i){ 
  18.             //swap方法是用于交换数组中2个位置的值(传入数组、下标),swap方法省略不写了。 
  19.             swap(arr,min,i); 
  20.         } 
  21.     } 

二、「 选择排序 」的性能怎么样?

我们按照之前文章中讲到的排序算法评估方法来对「 选择排序 」进行一下性能评估:

  • 时间复杂度:

选择排序原理就是在两层嵌套循环里进行对比和交换,所以简单来讲,其一般情况下的时间复杂度就是O(n*n)了。但如果仔细去分析的话,就得看具体的数据情况。但无论数据情况是怎样的,其元素比较的次数是一样的,因此无论是最好情况还是最坏情况,它的元素比较次数没区别。那再看看元素交换次数,如果待排序的数据本身就是有序的,其根本不需要交换元素,交换次数为0,但如果待排序的数据全部都是逆序的,那需要做n-1次元素交换。

因此,其选择排序的最好、最坏、平均情况下,其时间复杂度都是:O(n*n)。

  • 空间复杂度:

选择排序完全就是比较和交换数据,只需要一个辅助空间用来存储待比较的元素的小标,并没有消耗更多的额外空间,因此其空间复杂度是O(1)。

  • 排序稳定性:

选择排序算法不是稳定性排序算法。这里再解释一下稳定性排序是指:2个相等的元素,在排序前的相对前后位置和排序完成后的,相对前后位置保持一致。

选择排序为啥不是稳定性排序呢,举个例子:数组 6、7、6、2、8,在对其进行第一遍循环的时候,会将第一个位置的6与后面的2进行交换。此时,就已经将两个6的相对前后位置改变了。因此选择排序不是稳定性排序算法。

  • 算法复杂性:

选择排序的算法无论是其设计思路上,还是代码的编写上都不复杂,其算法复杂性是较为简单的。

以上,就是对数据结构中「 选择排序 」的一些思考,您有什么疑问吗?

码字不易啊,喜欢的话不妨转发朋友,或点击文章右下角的“在看”吧。😊

选择排序 算法 冒泡排序
上一篇:机器人警察正在将虚幻变成现实 下一篇:项目已开源,微软研究院用迁移学习训练自主无人机,可用于真实环境
评论
取消
暂无评论,快去成为第一个评论的人吧

更多资讯推荐

机器学习算法集锦:从贝叶斯到深度学习及各自优缺点

本文筛选并简单介绍了一些最常见算法类别,还为每一个类别列出了一些实际的算法并简单介绍了它们的优缺点。

佚名 ·  4天前
谷歌中国工程师提出颠覆性算法模型,Waymo实测可提高预测精准度

“周围的车辆和行人在接下来数秒中会做什么?”要实现安全的自动驾驶,这是一个必须回答的关键问题,这也就是自动驾驶领域中的行为预测问题。

DeepTech深科技 ·  4天前
有了K均值聚类,为什么还需要DBSCAN聚类算法?

聚类分析是一种无监督学习法,它将数据点分离成若干个特定的群或组,使得在某种意义上同一组中的数据点具有相似的性质,不同组中的数据点具有不同的性质。

读芯术 ·  2020-05-13 15:57:59
边做边思考,谷歌大脑提出并发RL算法,机械臂抓取速度提高一倍

RL 算法通常假设,在获取观测值、计算动作并执行期间环境状态不发生变化。这一假设在仿真环境中很容易实现,然而在真实机器人控制当中并不成立,很可能导致控制策略运行缓慢甚至失效。

机器之心 ·  2020-05-12 10:43:30
神经网络之父Hinton再审视34年前的奠基性成果,欲在大脑中搜寻AI方法的“存在”

直到现在,几乎你听说过的每一个关于人工智能的进步,仍基于 30 年前的一篇阐述多层神经网络训练方法的论文演变而来。那就是 Geoffrey Hinton 在 1986 年写下的《Learning representations by back-propagation errors》。

黄珊 ·  2020-05-02 10:54:13
生成“猫狗版”特朗普,造假脸工具StarGANv2被玩坏,算法已开源

如果你想用AI把特朗普的脸变成猫,又或者是把自己的脸与漂亮的奥妹结合起来,你会怎么办?也许你会想到两样AI工具。但是Deepfake生成人脸违和感太强,GAN生成假脸又很难深度定制。

晓查 ·  2020-04-28 13:34:53
Science子刊:人脑存在加速学习机制,算力赛过最新AI算法

机器学习虽然受人脑启发,但实验神经科学和ML两个学科已经70年没有沟通。以色列交叉学科团队发现,人脑存在加速学习适应机制,新机制人工神经网络计算能力远超最新AI算法。

佚名 ·  2020-04-24 12:50:50
AI的五个真正危险

AI的真正危险不是像SkyNet这样的有感觉的算法接管世界。 即使这种情况完全是科幻小说,也存在一些合理的问题。 不要惧怕技术,我们应该仔细识别它们并负责解决它们。 在这篇文章中,我将收集五个特别重要的领域,这些领域已经每天影响着我们的生活。

闻数起舞 ·  2020-04-22 10:52:44
Copyright©2005-2020 51CTO.COM 版权所有 未经许可 请勿转载