【排序算法】插入排序与选择排序详解

请添加图片描述

文章目录

  • 📝选择排序是什么?
    • 🌠选择排序思路
    • 🌉 直接选择排序
      • 🌠选择排序优化
      • 🌠优化方法
        • 🌉排序优化后问题
      • 🌠选择排序效率特性
    • 🌉插入排序
    • 🌠插入排序实现
  • 🚩总结


📝选择排序是什么?

选择排序是一种简单直观的排序算法。它的工作原理如下:在未排序序列中找到最小(大)元素,交换到起始位置,该元素为已排序序列的起始元素,继续在剩余未排序元素中找到最小(大)元素,交换到未排序序列起始位置,重复第二步,直到所有元素均排序完毕。

🌠选择排序思路

在元素集合array[i]–array[n-1]中选择关键码最大(小)的数据元素,若它不是这组元素中的最后一个(第一个)元素,则将它与这组元素中的最后一个(第一个)元素交换,在剩余的array[i]–array[n-2](array[i+1]–array[n-1])集合中,重复上述步骤,直到集合剩余1个元素

简单来说:就是在每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完 。

🌉 直接选择排序

例如:定义一个数组 int a[6] = { 9,5,7,2,3,6 };
在这里插入图片描述

  1. 首先:遍历第一趟数组,找出数组的最小值,与第一个数据交换
    在这里插入图片描述
  2. 然后遍历第二趟数组,继续找出最小值,与第二个数据交换
    在这里插入图片描述
  3. 然后遍历第三趟数组,继续找出最小值,与第三个数据交换
    在这里插入图片描述
    如此重复,然后当i等于n-1次选择时排完序,最后一个也有序,排序完成。
    在这里插入图片描述


代码:
上方观察:
选择要找几次?
6个数,一次选择1个,然后有序,第五次选择,5个都有序,最后一个有序。
n个数,选择n-1次,最后一个自然有序。
第一趟选择,下标范围是[0 ~ n-1]
第一趟选择,下标范围是[1 ~ n-1]
第一趟选择,下标范围是[2 ~ n-1]
.
.
.

void Swap(int* px, int* py)
{int tmp = *px;*px = *py;*py = tmp;
}void SelectSort(int*arr,int n) {for (int i = 0; i < n - 1; i++)//从0开始选,选到n-2次 {int mini = i;//设最小值是第1位for (int j = i + 1; j < n; j++)//首次从1开始到n-1每次比较 {								//查找是否有比最小值小的mini = arr[j] < arr[mini] ? j : mini;}Swap(&arr[i], &arr[mini]);}
}

思路总结:
在一个有n个元素中,进行排序,下标范围是0 ~ n-1,然后我们要在0 ~ n-1,中找到最小的数与0下标的数进行交换,接着在1 ~ n - 1下标中找最小值与1下标交换,然后下次就是2 ~ n - 1找最小值与2交换,每次找到最小值丢到最前面,接着交换,随即下标3,4,5…直到n - 1次选择都排完序,前n-1之前有序了,最后一个也有序。

特性总结:

时间复杂度:
外层for循环从0到n-2,共执行n-1次。内层for循环每次从i+1到n,共执行n-i-1次。所以总时间复杂度为:T(n) = Σ(n-1)(n-i-1) = Θ(n^2)选择排序的时间复杂度是O(n ^ 2)。
空间复杂度:
该算法只使用了一个临时变量mini来记录每次循环找到的最小元素的下标。且不需要额外的数组空间。所以空间复杂度为O(1)。

直接选择排序的特性总结:

  1. 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用
  2. 时间复杂度:O(N^2)
  3. 空间复杂度:O(1)
  4. 稳定性:不稳定

🌠选择排序优化

🌠优化方法

以上算法是每次找出最小的值放在指定位置,一共要找n-1次。如果我们每次不仅找到最小的值,还找到最大的值,将最小的与左端交换,最大的与右端交换,那么就少了一半的遍历次数,从而提高效率。

  1. 变量begin和变量end是数组的两端,MinMax在0位置,minmax分别找小和大的下标,i=begin+1,让begin+1到end的数都与begin比较。
    在这里插入图片描述

  2. 先交换min与begin位置的数值,再交换max与end位置的数值
    在这里插入图片描述

  3. begin右移,end左移,继续找大找小,继续交换
    在这里插入图片描述

  4. 重复上述操作,直到遍历完所有数组
    在这里插入图片描述

🌉排序优化后问题

若是max的位置与begin重合,则先让beginmin的位置交换,此时原max位置上的最大值已经被交换走,如果直接让end与现max位置交换,交换的值将是错误的。

  1. 当max与begin重合时,min在最小值位置
    在这里插入图片描述
  2. begin先与min的位置交换数据,此时max位置的已经不是最大值了
    在这里插入图片描述
  3. 当max再与end位置交换数据,排序就会出错
    在这里插入图片描述
    解决方法:

当max与begin重合时,先让begin与min交换,此时max原指向的最大值位置已改变,应对max进行修正,让其重新指向数组中真正的最大值位置。然后才能完成end与新max位置元素的交换。

  1. 当max与begin重合,并且begin此时完成了交换,此时最大值已经交换到了min所指向的位置
    在这里插入图片描述
  2. 修改max,让max来到min位置
    在这里插入图片描述
  3. 然后再让max与end交换
    在这里插入图片描述
    代码实现:
void SelectSort(int* a, int n)
{int begin = 0, end = n - 1;while (begin < end){int mini = begin, maxi = begin;//选出最小值和最大值的位置for (size_t i = begin + 1; i <= end; i++){if (a[i] < a[mini]){mini = i;}if (a[i] > a[maxi]){maxi = i;}}Swap(&a[begin], &a[mini]);if (maxi == begin){maxi = mini;}Swap(&a[end], &a[maxi]);++begin;--end;}
}

🌠选择排序效率特性

时间复杂度:O(N^2)
空间复杂度:O(1)
稳定性:不稳定

🌉插入排序

直接插入排序是一种简单的插入排序法,其基本思想是:**把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。**实际中我们玩扑克牌时,就用了插入排序的思想
在这里插入图片描述
如动图:
请添加图片描述
步骤:

  1. 从第一个元素开始,该元素可以认为已经被排序
  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描
  3. 如果该元素(已排序)大于新元素,将该元素移到下一位置
  4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
  5. 将新元素插入到该位置后
  6. 重复步骤2~5

通过不断地将当前元素插入到已经排好序的有序序列中,直到全部元素排完,即完成整个排序过程。

🌠插入排序实现

思路:第一个数天然有序,第二个数与代排有序序列第一个比较,小与插入,第三个数与前面两个元素比较,依次比较前面元素,然后比较完依次将后面元素依次插入到前面有序序列中,直到序列停止。
在这里插入图片描述
代码如下:

void InsertSort(int* arr, int n)
{for (int i = 0; i < n - 1; i++){//[0,end]  end+1//end记录当前要插入的元素位置 //end+1就是待插入元素的下标int end = i; int temp = arr[end + 1];//temp临时存储arr[end+1]这个待插入元素while (end >= 0){//如果temp小于arr[end],说明待插入元素应该插入在这个位置//将元素后移一位if (temp < arr[end]){arr[end + 1] = arr[end];end--;}//否则直接跳出循环else{break;}}//将待插入元素插入到正确位置arr[end + 1] = temp;}
}

时间复杂度:
最坏情况下为O(N*N),此时待排序列为逆序,或者说接近逆序
最好情况下为O(N),此时待排序列为升序,或者说接近升序。
元素集合越接近有序,直接插入排序算法的时间效率越高
空间复杂度:O(1),它是一种稳定的排序算法


🚩总结

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/769892.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

简单了解单例模式

什么是单例模式 对于一个类&#xff0c;只有一个实例化的对象&#xff0c;我们构建单例模式一般有两种&#xff1a;饿汉式和懒汉式 饿汉式 优点是无线程安全问题&#xff0c;类加载就创建对象缺点是占内存 class Singleton01{private static Singleton01 instance new Sing…

【JavaScript】JavaScript 程序流程控制 ⑥ ( while 循环概念 | while 循环语法结构 )

文章目录 一、while 循环1、while 循环概念2、while 循环语法结构 二、while 循环 - 代码示例1、打印数字2、计算 1 - 10 之和 一、while 循环 1、while 循环概念 在 JavaScript 中 , while 循环 是一种 " 循环控制语句 " , 使用该语句就可以 重复执行一段代码块 , …

瑞_Redis_商户查询缓存_什么是缓存

文章目录 项目介绍1 短信登录2 商户查询缓存2.1 什么是缓存2.1.1 缓存的应用场景2.1.2 为什么要使用缓存2.1.3 Web应用中缓存的作用2.1.4 Web应用中缓存的成本 附&#xff1a;缓存封装工具类 &#x1f64a; 前言&#xff1a;本文章为瑞_系列专栏之《Redis》的实战篇的商户查询缓…

C语言---------strlen的使用和模拟实现

字符串是以‘\0’作为结束标志&#xff0c;strlen函数的返回值是‘\0’前面的字符串的个数&#xff08;不包括‘\0’&#xff09; 注意 1&#xff0c;参数指向的字符串必须以‘\0’结束 2&#xff0c;函数的返回值必须以size_t,是无符号的 使用代码 ​ #include<stdio.…

学习刷题-13

3.23 hw机试【二叉树】 剑指offer32 剑指 offer32&#xff08;一、二、三&#xff09;_剑指offer 32-CSDN博客 从上到下打印二叉树I 一棵圣诞树记作根节点为 root 的二叉树&#xff0c;节点值为该位置装饰彩灯的颜色编号。请按照从 左 到 右 的顺序返回每一层彩灯编号。 输…

学习vue3第十一节(依赖注入:provide/inject)

本机介绍&#xff1a;provide/inject 注意&#xff1a;大家在看此小节时候&#xff0c;默认大家已经了解一些组件的使用方法 1、依赖注入的用途&#xff1a; 当嵌套层级多的时候&#xff0c;某个子组件需要较远层级的父组件数据时候&#xff0c;如果我们依然使用props 传递数…

关系型数据库mysql(6)备份与恢复

一.数据备份的重要性 &#xff08;1&#xff09;在生产环境中&#xff0c;数据的安全性至关重要 &#xff08;2&#xff09;任何数据的丢失都可能产生严重的后果 &#xff08;3&#xff09;造成数据丢失的原因 程序错误人为操作失误运算错误磁盘故障灾难&#xff08;如火灾…

背景减除(1)--bgslibrary Windows编译和使用

入侵监控领域中&#xff0c;在固定场景下&#xff0c;需要检测和监控的入侵物体种类繁多&#xff0c;无法具体穷尽。传统的CV算法提取的特征应用场景有限&#xff0c;无法完成大量物体的监控&#xff1b;深度学习目标检测方法没法收集到无穷无尽的物体种类&#xff0c;因此监督…

C语言----strcpy和strcat的使用和模拟实现

一&#xff0c;strcpy()函数 strcpy() 函数是 C语言中一个非常重要的字符串处理函数&#xff0c;其功能是将一个字符串复制到另一个字符串中。该函数原型如下&#xff1a; char*strcpy(char*dest,const char*src) 其中&#xff0c;dest 表示目标字符串&#xff0c;即将被复制到…

【HDFS】DatanodeAdminBackoffMonitor退役节点极慢的问题定位

一、现象: 下节点特别慢。10台节点,每台大约需要退役60w个块。但是3个小时才退役了3000多个块。 NN侧如下日志,可以看到30秒只退役了512-494 = 20个块,这要是退役600w个块,得猴年马月? 2024-03-19 14:44:42,952 INFO org.apache.hadoop.hdfs.server.blockmanagement.D…

浅析扩散模型与图像生成【应用篇】(十一)——DDIBs

11. Dual Diffusion Implicit Bridges for Image-to-Image Translation 该文提出一种双扩散隐式桥&#xff08;Dual Diffusion Implicit Bridges&#xff0c; DDIBs&#xff09;方法用于图像转换&#xff0c;其最大的特点在于处理源域图像的模型和处理目标域图像的模型是彼此分…

华为防火墙二层墙(VAN/SVI/单臂路由)

二层墙只能做地址池形式的NAT。 交换机安全策略防火墙二层墙 路由器安全策略防火墙三层墙 交换机的光口是不能直接插线的&#xff0c;光模块&#xff0c;包括进和出 长距离&#xff1a;单模 短距离&#xff1a;多模 防火墙自身的ping流量需要单独配置

一篇复现Docker镜像操作与容器操作

华子目录 Docker镜像操作创建镜像方式1docker commit示例 方式2docker import示例1&#xff1a;从本地文件系统导入示例2&#xff1a;从远程URL导入注意事项 方式3docker build示例1&#xff1a;构建镜像并指定名称和标签示例2&#xff1a;使用自定义的 Dockerfile 路径构建镜像…

Unity连接MySQL踩坑,问题处理记录

用的unity2021版本&#xff0c;MySQL是官方下载的最新版8.0.36. 安装MySQL时&#xff0c;过去如果安装过&#xff0c;一定要删干净&#xff0c;单纯的卸载不行&#xff0c;网上有很多教程。 MySQL安装完成后&#xff0c;将安装目录的MySql.Data.dll文件放入unity项目的Plugin…

数据运营常用的8大模型

✅作者简介&#xff1a;《数据运营&#xff1a;数据分析模型撬动新零售实战》作者、《数据实践之美》作者、数据科技公司创始人、多次参加国家级大数据行业标准研讨及制定、高端企培合作讲师。 &#x1f338;公众号&#xff1a;风姑娘的数字视角&#xff0c;免费分享数据应用相…

202447读书笔记|《围炉夜话》——多记先正格言,胸中方有主宰 闲看他人行事,眼前即是规箴

202447读书笔记|《围炉夜话》——多记先正格言&#xff0c;胸中方有主宰&#xff1b;闲看他人行事&#xff0c;眼前即是规箴 围炉夜话 《围炉夜话&#xff08;读客三个圈经典文库&#xff09;》作者王永彬。读《围炉夜话》&#xff0c;可以掌握君子安身立业的大智慧&#xff01…

【Canvas与艺术】暗蓝网格汽车速度仪表盘

【关键点】 采用线性渐变色&#xff0c;使上深下浅的圆有凹下效果&#xff0c;使上浅下深的圆有凸起效果&#xff0c;两者结合就有立体圆钮的感觉。 【图例】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type&quo…

2015年认证杯SPSSPRO杯数学建模C题(第二阶段)荒漠区动植物关系的研究全过程文档及程序

2015年认证杯SPSSPRO杯数学建模 C题 荒漠区动植物关系的研究 原题再现&#xff1a; 环境与发展是当今世界所普遍关注的重大问题, 随着全球与区域经济的迅猛发展, 人类也正以前所未有的规模和强度影响着环境、改变着环境, 使全球的生命支持系统受到了严重创伤, 出现了全球变暖…

R语言基础入门

1.保存或加载工作空间 改变工作目录——进行文件读写&#xff0c;默认去指定文件进行操作。&#xff08;使用R时&#xff0c;最好先设定工作目录&#xff08;setwd(),getwd()&#xff09;&#xff09; setwd(“工作文件路径”)&#xff1a;建立工作目录 getwd&#xff08;&…

【STM32嵌入式系统设计与开发】——9Timer(定时器中断实验)

这里写目录标题 一、任务描述二、任务实施1、ActiveBeep工程文件夹创建2、函数编辑&#xff08;1&#xff09;主函数编辑&#xff08;2&#xff09;USART1初始化函数(usart1_init())&#xff08;3&#xff09;USART数据发送函数&#xff08; USART1_Send_Data&#xff08;&…