当前位置: 首页 > news >正文

【探索数据结构与算法】插入排序:原理、实现与分析(图文详解)

目录

一、插入排序 算法思想

二、插入排序 算法步骤 

四、复杂度分析

时间复杂度:O(n^2)

空间复杂度:O(1) 

稳定性:稳定算法 

五、应用场景 


💓 博客主页:C-SDN花园GGbond

⏩ 文章专栏:探索数据结构与算法

一、插入排序 算法思想

**插入排序(Insert Sort)**是一种最简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。它的思想类似于我们打扑克牌时的整理 

二、插入排序 算法步骤 

  1. 将第一待排序 序列的第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
  2. 从尾到头依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)     
  3. 具体步骤是这样的:
    (以排升序为例)

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

动图 

三、C语言代码实现 

//插入排序
void InsertSort(int* a, int len)
{//0到end有序,插入a[end+1]for (int i = 0; i < len - 1; i++){int end = i;int tmp = a[i + 1];while (end >= 0){if (a[end]>tmp){a[end + 1] = a[end];end--;}else{break;}}a[end + 1] = tmp;}
}

四、复杂度分析

时间复杂度:O(n^2)

最好情况(O(n)):

当输入数组已经是排序状态时,插入排序的性能最优。此时,每个元素只需与其前面的一个元素进行比较(因为它已经位于正确的位置),因此总共需要进行大约n-1次比较,时间复杂度为O(n)。这里的n是数组的长度。

最坏情况(O(n^2)):

当输入数组完全逆序时,插入排序的性能最差。对于每个元素,都需要与其前面的所有元素进行比较,直到找到合适的位置。因此,第i个元素需要比较i次(其中i从2开始,直到n),总共需要进行的比较次数大约为1 + 2 + 3 + ... + (n-1) = n(n-1)/2,时间复杂度为O(n^2)。

平均情况(O(n^2)):

对于随机排列的数组,插入排序的平均时间复杂度也是O(n^2)。这是因为大部分情况下,元素都需要进行多次移动和比较才能找到正确的位置。

空间复杂度:O(1) 

插入排序是一种原地排序算法,它只需要一个额外的存储空间来暂存当前需要插入的元素(即“key”),而不需要额外的数组来存储排序过程中的数据。因此,其空间复杂度为O(1)。

稳定性:稳定算法 

 插入排序是一种稳定的排序算法。在插入排序过程中,如果两个相等的元素,后面的元素不会移动到前面元素的前面,而是直接插入到与它相等的元素之后,从而保持了原有的相对顺序。

五、应用场景 

插入排序虽然在大规模数据集上可能不是最高效的排序算法,但其简单性、稳定性和在某些特定场景下的高效性使得它在许多实际应用中仍然具有一定的价值。

小规模数据集:由于插入排序在小规模数据集上表现良好,且实现简单,因此常用于对少量数据进行排序的场景。快速排序的小区间优化
几乎有序的数据集:当数据已经接近有序时,插入排序的性能会显著提高。因为此时大部分元素已经处于或接近其最终位置,所需的比较和移动次数会大幅减少。
链表排序:由于链表不支持像数组那样的随机访问,因此在链表上进行排序时,插入排序成为了一个非常合适的选择。它可以通过改变节点的指针来实现元素的移动,而不需要额外的存储空间。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【C++篇】引领C++模板初体验:泛型编程的力量与妙用
  • ElasticSearch学习笔记
  • FFmpeg开发笔记(五十六)使用Media3的Exoplayer播放网络视频
  • 「C++系列」动态内存
  • 超越sora,最新文生视频CogVideoX-5b模型分享
  • ChatGPT 在国内使用的方法
  • aws 容器镜像仓库操作
  • 数据结构——二叉搜索树
  • Java调用数据库 笔记05(查询篇)
  • 植物大战僵尸【源代码分享+核心思路讲解】
  • 【MySQL】获取最近7天和最近14天的订单数量,使用MySQL详细写出,使用不同的方法
  • openeuler 22.03 lts sp4 使用 kubeadm 部署 k8s-v1.28.2 高可用集群
  • CTF 技能树 LOG -GIT泄露 笔记
  • 身份安全风险不断上升:企业为何必须立即采取行动
  • Nginx反向代理出现502 Bad Gateway问题的解决方案
  • 【EOS】Cleos基础
  • 【node学习】协程
  • Apache的基本使用
  • django开发-定时任务的使用
  • docker python 配置
  • EventListener原理
  • Linux编程学习笔记 | Linux IO学习[1] - 文件IO
  • Netty 框架总结「ChannelHandler 及 EventLoop」
  • Next.js之基础概念(二)
  • node 版本过低
  • php中curl和soap方式请求服务超时问题
  • supervisor 永不挂掉的进程 安装以及使用
  • web标准化(下)
  • 产品三维模型在线预览
  • 分享一份非常强势的Android面试题
  • 警报:线上事故之CountDownLatch的威力
  • 可能是历史上最全的CC0版权可以免费商用的图片网站
  • 如何将自己的网站分享到QQ空间,微信,微博等等
  • 入手阿里云新服务器的部署NODE
  • 微信支付JSAPI,实测!终极方案
  • 中文输入法与React文本输入框的问题与解决方案
  • ​人工智能书单(数学基础篇)
  • ###C语言程序设计-----C语言学习(3)#
  • #我与Java虚拟机的故事#连载05:Java虚拟机的修炼之道
  • (1)安装hadoop之虚拟机准备(配置IP与主机名)
  • (附程序)AD采集中的10种经典软件滤波程序优缺点分析
  • (论文阅读22/100)Learning a Deep Compact Image Representation for Visual Tracking
  • (转)mysql使用Navicat 导出和导入数据库
  • ... 是什么 ?... 有什么用处?
  • .NET Core中的去虚
  • .NET Framework 和 .NET Core 在默认情况下垃圾回收(GC)机制的不同(局部变量部分)
  • .NET 中让 Task 支持带超时的异步等待
  • .net连接oracle数据库
  • .py文件应该怎样打开?
  • .secret勒索病毒数据恢复|金蝶、用友、管家婆、OA、速达、ERP等软件数据库恢复
  • @ 代码随想录算法训练营第8周(C语言)|Day57(动态规划)
  • @NestedConfigurationProperty 注解用法
  • @synthesize和@dynamic分别有什么作用?
  • [AIGC] MySQL存储引擎详解
  • [Android 数据通信] android cmwap接入点