『初阶数据结构 • C语言』⑤ - 选择排序

这篇具有很好参考价值的文章主要介绍了『初阶数据结构 • C语言』⑤ - 选择排序。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

本文内容借鉴一本我非常喜欢的书——《数据结构与算法图解》。学习之余,我决定把这本书精彩的部分摘录出来与大家分享。   

目录

写在前面

1.选择排序

2.选择排序实战

3.选择排序的实现

4.选择排序的效率

5.忽略常数

6.大O的作用

7.总结


 『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

 文章来源地址https://www.toymoban.com/news/detail-622635.html

写在前面

大 O 是一种能够比较算法效率,并告诉我们在特定环境下应采用何种算法的伟大工具。但我们不能完全依赖于它。

因为有时候即使两种算法的大 O 记法完全一样,但实际上其中一个比另一个要快得多。

本章我们就来学习如何分辨那些效率貌似一样的算法,从而选出较快的那个。


1.选择排序

上一章分析了冒泡排序算法,其效率是 O(N^2 )。现在我们再来探索另一种排序算法,选择排
序,并将它跟冒泡排序对比一下。

选择排序的步骤如下。

(1) 从左至右检查数组的每个格子,找出值最小的那个。在此过程中,我们会用一个变量来记住检查过的数字的最小值(事实上记住的是索引,但为了看起来方便,下图就直接写出数值)。如果一个格子中的数字比记录的最小值还要小,就把变量改成该格子的索引,如图所示。

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

(2) 知道哪个格子的值最小之后,将该格与本次检查的起点交换。第 1 次检查的起点是索引 0,
第 2 次是索引 1,以此类推。下图展示的是第一次检查后的交换动作。

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

(3) 重复第(1) (2)步,直至数组排好序。 


2.选择排序实战

以数组 [4,2,7,1,3] 为例,步骤如下。

开始第 1轮检查。

首先读取索引 0。根据此算法的定义,它是目前遇到的最小值(因为现在只检查了一个格子),于是记下其索引。

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

第 1步:将索引 1的值 2与目前的最小值 4进行比较。

2比 4还要小,于是将目前的最小值改为 2。

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

第 2步:再与下一个值做比较。因为 7大于 2,所以最小值还是 2。

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

第 3步:将 1和目前的最小值做比较。 

1比 2还要小,于是目前的最小值更新为 1。

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

第 4步:比较 3和目前的最小值 1。因为现在已经走到数组尽头了,所以可以断定 1是整个
数组的最小值。 

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

第 5步:本次检查的起点是索引 0,不管那里的值是什么,我们都应该将最小值 1换到那里。

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

现在 1就排到正确的位置上了。

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

可以开始第 2轮检查了。 

准备工作:因为索引 0的值已符合其排位,所以这一轮从下一个格子开始,即索引 1,其值为 2,也是目前本轮所遇到的最小值。

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

第 6步:将 7跟目前的最小值 2进行比较。因为 2小于 7,所以最小值仍为 2。

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

 第 7步:将 4跟目前的最小值 2进行比较。因为 2小于 4,所以最小值仍为 2。

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

第 8步:将 3跟目前的最小值 2进行比较。因为 2小于 3,所以最小值仍为 2。 

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

又走到数组尽头了。本轮不需要做任何交换,2已在其正确位置上。于是第 2轮检查结束,现在数组如下图所示。 、

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

开始第 3轮检查。 

准备工作:从索引 2起,其值为 7。于是本轮目前最小值为 7。

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

第 9 步:比较 4 与 7。

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

将 4 记为目前的最小值。 

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

第 10 步:遇到 3,它比 4 还小。

于是 3 成了目前的最小值。

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构第 11 步:到数组尽头了,将 3 跟本轮起点 7 进行交换。 

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

于是 3 排到正确位置上了。 

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

虽然我们可以看到现在整个数组都有序了,但计算机是看不到的,它只会继续第 4轮检查。

准备工作:此轮检查从索引 3开始,其值 4是目前的最小值。

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

第 12步:比较 4和 7。 

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

4仍为最小值,而且它也处于本轮起点,因此无须任何交换。

因为最后一个格子左侧的那些值都已在各自的正确位置上,所以最后一格也必然正确,于是排序结束。

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构


3.选择排序的实现

下面是用C语言实现的选择排序:

void SelectSort(int arr[], int n)//升序
{
	for (int i = 0; i < n-1; i++) //n个数,只需排好n-1个,剩下的一个自然在正确的位置上
	{
		int min = i;      //用min来记录最小值的索引(下标)         
		
        for (int j = i+1; j < n; j++)  //从i索引的后一个开始比较
		{
			if (arr[j] < arr[min])
			{
				min = j;            //找到比自己小的数的索引,并成为它
			}
		}
		if (min != i)               //如果min的值改变,则与i处的值交换
		{
			int tmp = arr[i];
			arr[i] = arr[min];
			arr[min] = tmp;
		}
	}
}

下面来进行分析:

for (int i = 0; i < n-1; i++) 

这个外层的循环代表每一轮检查。在一轮检查之初,我们会先记住目前的最小值的索引。

int min = i;

因此每轮开始时 min 都会是该轮的起点索引 i 。

注意我们实际上记录的是最小值的索引,而非最小值本身。于是,第 1 轮开始时最小值的索引是 0,到第 2 轮则是 1,以此类推。

for (int j = i+1; j < n; j++)

这个内层循环控制的是找出最小值的索引的过程。

if (arr[j] < arr[min])
{
	min = j;            
}

循环内逐个检查数组未排序的格子,若遇到比之前记录的本轮最小值还小的格子值,就将min更新为该格子的索引。

内层循环结束时,会得到未排序数值中最小值的索引。

if (min != i)
{
	int tmp = arr[i];
	arr[i] = arr[min];
	arr[min] = tmp;
}

然后再看看这个最小值是否已在正确位置,即该索引是否等于 i 。如果不是,就将 i 所指的值与最小值交换。


4.选择排序的效率

选择排序的步骤可分为两类:比较和交换。

若有 N个元素,就会有 (N - 1) + (N - 2) + (N - 3) + … + 1次比较。

但每轮的交换最多只有 1 次。如果该轮的最小值已在正确位置,就无须交换,否则要做 1 次交换。相比之下,冒泡排序在最坏情况(完全逆序)时,每次比较过后都要进行 1 次交换。

下表为冒泡排序和选择排序的并列对比。

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

从表中可以清晰地看到,选择排序的步数大概只有冒泡排序的一半,即选择排序比冒泡排序快一倍。 


5.忽略常数

但有趣的是,选择排序的大 O记法跟冒泡排序是一样的。

还记得我们说过,大 O记法用来表示步数与数据量的关系。所以你可能会以为步数约为 N^2的一半的选择排序,其大 O会写成 O(N ^2/ 2),以表示 N个元素需要 N ^2 / 2步。如下表所示。

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

但事实上,选择排序的大 O记法为 O(N^2 ),跟冒泡排序一样。这是因为大 O记法的一条重要
规则:

大 O 记法忽略常数。


6.大O的作用

尽管不能比较冒泡排序和选择排序,大 O 还是很重要的,因为它能够区分不同算法的长期增长率。当数据量达到一定程度时,O(N)的算法就会永远快过 O(N^2 ),无论这个 O(N)实际上是O(2N)还是 O(100N)。

下图为 O(N)和 O(N^2 )的对比。

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

这就是大 O 记法忽略常数的原因。大 O 记法只表明,对于不同分类,存在一临界点,在这一点之后,一类算法会快于另一类,并永远保持下去。至于这个点在哪里,大 O并不关心。

因此,不需要写成 O(100N),归类到 O(N)就好了。


7.总结

现在我们已经掌握了一些非常强大的算法分析手法。我们能够使用大 O去判断各种算法的效率,即便两种算法的大 O记法一样,也知道如何对比它们。不过在对比算法时,还需要考虑一个重要因素。至今我们关注的都是最坏情况下算法会跑得多慢,但其实最坏情况并不总会发生。没错,我们遇到的大都是平均情况。下一章,我们会学习怎样顾及所有情况。

『初阶数据结构 • C语言』⑤ - 选择排序,排序算法(C语言版),新星计划免费学习专栏·数据结构与算法,排序算法,算法,数据结构

 

到了这里,关于『初阶数据结构 • C语言』⑤ - 选择排序的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构初阶】八大排序算法+时空复杂度

    学会控制自己是人生的必修课 1.直接插入排序思想: 假设现在已经有一个有序序列,如果有一个数字插入到这段序列的末尾,我们会选择拿这个数和它前面的每个数字都比较一遍,如果前面的数字比他大,那我们就让前面的数字赋值到这个被插入的数字位置,依次与前面的数

    2024年02月01日
    浏览(117)
  • 【数据结构与算法】排序算法:冒泡排序,冒泡排序优化,选择排序、选择排序优化

    目录 一、冒泡排序 1、冒泡排序思想 2、冒泡排序算法的性能分析 代码实现: 二、选择排序 1、选择排序思想 2、选择排序算法的性能分析  代码实现: 1、冒泡排序思想 冒泡排序的基本思想是通过相邻元素之间的比较和交换来逐步将最大(或最小)的元素移到右边(或左边

    2024年01月19日
    浏览(50)
  • 『初阶数据结构 • C语言』⑬ - 堆排序详解【附完整源码】

     = 目录 0.写在前面 1.什么是堆? 2. 堆排序 2.1 建堆 2.1.1 AdjustUp(向上调整算法) 2.1.2 AdjustDown(向下调整算法) 2.2 两种建堆算法的时间复杂度 2.2.1 AdjustUp建堆的时间复杂度 2.2.2 AdjustDown建堆的时间复杂度 2.3 排序 3.堆排序的时间复杂度 完整源码 你是否对堆排序早有耳闻?身

    2024年02月16日
    浏览(37)
  • 数据结构与算法—插入排序&选择排序

    目录 一、排序的概念 二、插入排序   1、直接插入排序  特性总结: 2、希尔排序 特性总结:  三、选择排序 1、直接选择排序  特性总结: 2、堆排序—排升序(建大堆) 向下调整函数 堆排序函数 特性总结: 代码完整版:   头文件  函数文件  测试文件 排序 :所谓排序,

    2024年01月20日
    浏览(63)
  • 【数据结构与算法】排序算法(选择排序,冒泡排序,插入排序,希尔排序)

    基本概念这了就不浪费时间解释了,这四种都是很简单的排序方式,本专栏后续文章会出归并排序,计数排序,快速排序,堆排序,桶排序等排序算法,今天这篇文章中给出选择排序,冒泡排序,插入排序和希尔排序的实现; 如果发现文章中有错误,还请大家指出来,我会非

    2024年02月15日
    浏览(86)
  • 数据结构算法--2 冒泡排序,选择排序,插入排序

    思想就是将相邻元素两两比较,当一个元素大于右侧相邻元素时,交换他们的位置,小于右侧元素时,位置不变,最终序列中的最大元素,像气泡一样,到了最右侧。 这时冒泡排序第一轮结束,数列最右侧元素9的位置可认为是一个有序区,有序区目前有一个元素. 第二轮排序

    2024年02月13日
    浏览(64)
  • 【数据结构】八大排序之简单选择排序算法

    🦄 个人主页 :修修修也 🎏 所属专栏 :数据结构 ⚙️ 操作环境 : Visual Studio 2022 目录 一.简单选择排序简介及思路 二.简单选择排序的代码实现 三.简单选择排序的优化 四.简单选择排序的时间复杂度分析 结语 简单选择排序算法(Simple Selection Sort) 是一种简单直观的 选择排序算

    2024年02月01日
    浏览(78)
  • 【数据结构与算法】:选择排序与快速排序

    🔥 个人主页 : Quitecoder 🔥 专栏 :数据结构与算法 我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:腾讯云 欢迎来到排序的第二个部分:选择排序与快速排序! 选择排序是一种简单直观的比较排序算法。该算法的基本思想是在每一轮中选出当前未排序部分的最

    2024年03月17日
    浏览(52)
  • 【数据结构】排序算法(一)—>插入排序、希尔排序、选择排序、堆排序

    👀 樊梓慕: 个人主页   🎥 个人专栏: 《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》 🌝 每一个不曾起舞的日子,都是对生命的辜负 目录 前言 1.直接插入排序 2.希尔排序 3.直接选择排序 4.堆排序 本篇文章博主将介绍排序算法中的插入排序:直接

    2024年02月08日
    浏览(49)
  • 【数据结构】常见排序算法——常见排序介绍、选择排序(直接选择排序、堆排序)交换排序(冒泡排序)

      选择排序是一种简单但不高效的排序算法,其基本思想是从待排序的数据中选择最小(或最大)的元素放到已排序的数据末尾。具体操作步骤如下: (1)找到数据中最小的元素,并把它交换到第一个位置; (2)在剩下未排序的元素中找到最小的元素,并把它交换到已排

    2024年02月04日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包