直接插入排序(python实现)
这篇博文用来介绍直接插入排序
直接插入排序基本思想:
每次将一个待排序的记录插入到已经排好序的数据区中,直到全部插入完为止
直接插入排序算法思路:
在直接插入排序中,数据元素分为了有序区和无序区两个部分,在这里我们将列表左边部分作为有序区,列表右边部分作为无序区,有序区和无序区的大小是随着排序的进行而变化的。
如最开始列表是无序的,所以有序区长度为1,无序区长度为列表长度-1,排序结束后,列表变为有序,则有序区长度为列表长度,无序区长度为0.
具体步骤为:
排序过程中每次从无序区中取出第一个元素,将它插入到有序区中的适当位置(即该元素放在此位置,有序区仍然有序),使之成为新的有序区,重复n-1次可完成排序过程。
假设需要将列表从小到大排序
想要将从无序区中取出的第一个元素temp插入到有序区中的适当位置,需要有一个循环遍历的过程,即从该元素位置处依次向前比较,会有两种情况:
1,前面的元素waitsortlist[j-1]大于temp,则temp需要继续向前比较,同时大于temp的元素需要后移一位
2,前面的元素waitsortlist[j-1]小于等于temp,则temp不需要继续比较了,因为temp大于有序区中最大的元素,有序区伸展一位,包含temp
另外还需要考虑 j 的边界问题,因为会用到 j-1,所以 j 需要>=1防止越界,对于无序区某一个元素temp的直接插入代码如下:
1 2 3 4 5 6 7 8 | temp = waitsortlist[j] while j> = 1 : if temp<waitsortlist[j - 1 ]: waitsortlist[j] = waitsortlist[j - 1 ] j = j - 1 else : break waitsortlist[j] = temp |
外层是一个列表的遍历,加上上面的代码为:
1 2 3 4 5 6 7 8 9 10 11 12 13 | i = 0 j = i + 1 while j< len (waitsortlist): temp = waitsortlist[j] while j> = 1 : if temp<waitsortlist[j - 1 ]: waitsortlist[j] = waitsortlist[j - 1 ] j = j - 1 else : break waitsortlist[j] = temp i = i + 1 j = i + 1 |
可以看出,列表的第一个元素必为有序区,遍历的过程中不断扩大有序区的范围,对于列表某一个元素来说,就是将其插入在有序区中适当的位置,外层循环遍历结束后,有序区也扩充为列表长度,即排序结束。
该算法的时间复杂度为O(n^2),因为有两层循环,时间开销比较大,空间复杂度为O(1),只是用了常数阶的空间来存储变量,用以直接插入排序
全部代码为(实际上看了前面的相信你已经能写出来了:D
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ''' 直接插入排序 ''' def DirectInsertionSort(waitsortlist): i = 0 j = i + 1 while j< len (waitsortlist): temp = waitsortlist[j] while j> = 1 : if temp<waitsortlist[j - 1 ]: waitsortlist[j] = waitsortlist[j - 1 ] j = j - 1 else : break waitsortlist[j] = temp i = i + 1 j = i + 1 return waitsortlist if __name__ = = '__main__' : waitsortlist = [ 9 , 8 , 7 , 6 , 5 , 4 , 3 , 2 , 1 , 0 ] print (DirectInsertionSort(waitsortlist)) |
运行结果为:
直接插入排序 (带监视哨):
哨兵的概念:一切为简化边界条件而引入的附加结点(元素)均可称为哨兵。
在上面的代码我们可以看到有这一段:
1 | while j> = 1 : |
内循环每一次比较前都需要判断 j 是否越界,有没有不需要判断的办法呢?当然有,这就是哨兵的作用
将上面的代码改为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | def DirectInsertionSortEye(waitsortlist): i = 1 j = i + 1 while j< len (waitsortlist): temp = waitsortlist[j] waitsortlist[ 0 ] = temp while temp<waitsortlist[j - 1 ]: waitsortlist[j] = waitsortlist[j - 1 ] j = j - 1 waitsortlist[j] = temp i = i + 1 j = i + 1 return waitsortlist if __name__ = = '__main__' : waitsortlist = [ 0 , 9 , 8 , 7 , 6 , 5 , 4 , 3 , 2 , 1 , 0 ] print (DirectInsertionSortEye(waitsortlist)) |
输出的结果为:
我们将waitsortlist[0]设置为哨兵,传入列表的时候,该位置也不能够放置有效元素,用列表一个元素的空间判断越界与否的比较时间。可以看出,一次循环少判断一次,n次循环少判断n次,当数据量较大时,很明显是优于不带监视哨的直接插入排序。
带监视哨的直接插入排序思想也很简单,在原有基础上稍加修改即可,这里不再赘述。
__EOF__

本文链接:https://www.cnblogs.com/Cl0ud/p/12942704.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!