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

直接插入排序

用一个生动的例子来比喻直接插入排序:打扑克时理牌的行为

在理牌的时候,我们会根据牌面的大小将其插入合适的位置,那么直接插入排序也是如此

直接插入排序:

直接插入排序可以看作是待排序的内容分为两个部分,一部分为有序一部分为无序整个排序过程就是每次都从无序的部分里取出第一个元素,和有序部分的尾部元素开始往前进行比较,直到找到合适的位置进行插入就停止

过程模拟:

假设现在有一个序列如:2 5 3 0 6 4 需要对其使用直接插入排序进行升序排序

那么第一趟排序,第一个元素[ 2 ]就是有序部分,剩下的元素就为无序部分

①取出无序部分的第一个元素5,和有序部分的元素 [ 2 ] 进行比较,选择合适的位置插入

②因为5>2,所以 5 就放在 2 的后面,不进行移动改变,此时前两个数是有序的[ 2,5 ]

此时第二趟排序,有序部分为[ 2,5 ],剩下的元素就为无序部分

因为有序部分不止一个元素,使用end来指向有序部分中的元素,来控制两个部分之间的元素比较

使用end指向有序部分中待比较的位置,使用变量tmp保存待插入元素的值,因为比较过程中可能会挪动覆盖掉待插入的值,所以提前保存

①取出无序部分的第一个元素 即待插入的元素,用tmp变量保存起来,再和有序部分的元素 [ 2,5 ] 进行比较,使用end来指向每次待比较的元素,选择合适的位置插入

②使用 tmp 的值end 指向位置(有序部分中最后一个位置)的值即 5 进行比较,因为3<5,所以 end 位置的值即 5 移动到end+1的位置即 3 的位置或者说5的下一个位置,3就被覆盖

③此时比较完有序部分中的一个元素,end就进行减减--,指向有序部分中下一个待比较的元素此时该元素为 2 ,因为tmp的值即 3>2 ,所以此时tmp就插入到end的下一个位置即end+1的位置

只要将tmp插入到合适的位置,那么该躺排序就结束

进入第三趟排序,有序部分为[ 2,3,5 ],剩下的元素就为无序部分

此时待插入的元素为 0 ,tmp=0,end就指向有序部分末尾的位置,即5所在位置

① 使用tmp的值 0 与 end 指向的位置进行比较,0<5,end位置的值往后挪动即挪到到end+1的位置,即5覆盖掉0

② end进行减减--,指向有序部分的下一个待比较元素即3,因为tmp为0,0<3,所以3挪动到end+1的位置

③ end继续减减--,指向有序部分的下一个待比较元素即2,因为tmp为0,0<2,所以2挪动到end+1的位置

 ③ end再继续减减--,但是此时有序部分已经全部都比较完毕了,end--后等于-1,此时tmp的值就直接插入到end+1的位置即序列的第一个位置

那么剩下的无序部分依此类推,每次都取出无序部分的第一个元素与有序部分进行比较,直到找到合适的位置进行插入就结束

代码逻辑抽象:

先来单趟的逻辑一个元素进行插入的过程

无论是通过找到比 tmp 小的元素而找到插入的位置结束即break,还是通过将有序部分的元素都比较完,而找到插入的位置结束即end<0,会发现最终插入的位置都是end+1的位置即end指向的位置的下一个

// 数组 int a[]={2,5,3,0,6,4}
int end;
int tmp=a[end+1];
while(end>=0) // 当有序部分都比较完了就结束
{if( tmp < a[end] ){a[end+1]=a[end]; // 元素向后挪动end--;}else{break; // tmp大于比较的元素,即找到合适的位置,结束比较}
}
// 循环结束即找到合适的位置,即为end+1,将tmp插入
a[end+1]=tmp;

完整代码:

// 数组 int a[]={2,5,3,0,6,4}
void InsertSort(int* a,int n)
{// 外层循环,控制有序部分范围,即end指向的位置for(int i=0;i<n-1;i++){int end=i;int tmp=a[end+1];while(end>=0) // 当有序部分都比较完了就结束{if( tmp < a[end] ){a[end+1]=a[end]; // 元素向后挪动end--;}else{break; // tmp大于比较的元素,即找到合适的位置,结束比较}}// 循环结束即找到合适的位置,即为end+1,将tmp插入a[end+1]=tmp;}
}

时间复杂度分析:

从代码来看最坏时间复杂度是O(N^2)如待排序的序列为逆序

最好时间复杂度是O(N)即顺序有序或接近有序,那就相当于遍历了一遍

http://www.xdnf.cn/news/793747.html

相关文章:

  • CppCon 2014 学习:The New Old Thing
  • invalid domain [10.230.90.11:2025] was specified for this cookie异常原因分析
  • 小黑一步步探索大模型应用:langchain中AgentExecutor的call方法初探demo(智能体调用)
  • OD 算法题 B卷【通过软盘拷贝文件】
  • C++结构体初始化方式区别
  • Windows下将Nginx设置注册安装为服务方法!
  • 爱普生有源晶振SG2520CBN在通信基站中的应用
  • UVa12298 Super Joker II
  • AI一周事件(2025年5月27日-6月2日)
  • JavaScript 递归构建树形结构详解
  • linux学习第19、20天(父子进程)
  • 选择正确的电平转换解决方案
  • HertzBeat的告警规则如何配置?
  • Flowith,有一种Agent叫无限
  • MyBatis 深度解析:高效 Java 持久层框架实践指南(基于 3.5.10)
  • 黑马程序员TypeScript课程笔记—class篇
  • windows环境下Ubuntu系统怎么重置root密码
  • 鸿蒙5.0项目开发——横竖屏切换开发
  • 深入解析 Java 中的 synchronized:从使用到底层原理的全面详解
  • C++中锁和原子操作的区别及取舍
  • 楼宇自控系统联动暖通空调:解密建筑环境舒适度提升路径
  • 域自适应 (Domain Adaptation,DA)基础
  • JS对数据类型的检测
  • TitanIDE智算版:一键开启云端算法开发环境
  • Servlet 生命周期
  • 高性能MCU的MPU与Cache优化详解
  • 线性动态规划
  • 张雪峰为9岁女儿申请40个左右商标!
  • 超声波粒度仪市场报告:行业现状、竞争格局与未来趋势分析
  • 原子操作与非原子操作