插入排序及其优化-排序算法连载(三)

本文深入解析了插入排序算法,包括其工作原理、实现过程、时间与空间复杂度分析、稳定性讨论及优化策略。通过实例和代码演示,展示了算法的运行机制,并对比了优化前后的执行效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

插入排序,是最经典的排序算法。下面从以下几个方面介绍该算法。

  1. 算法原理[algorithm principle]
  2. 算法实现[algorithm implementation]
  3. 时间复杂度[time complexity]
  4. 空间复杂度[space complexity]
  5. 稳定性[stability]
  6. 算法优化-(监视哨)

1.算法原理

将无序元素,分别插入到有序系列合适位置:

  • step1:在一个序列划分为【 有序区域:无序序列 】
  • step2 :在无序区域中选择一个元素,插入到有序区域合适的位置中
  • step3: 循环step2 ,直到只剩下一个元素,排序结束。

1.1 图解算法

假设a=[1,3,2,9,7,2],下面对a进行升序排列。
在这里插入图片描述

1.1.1 进行首次循环

在这里插入图片描述
在这里插入图片描述
到此首次循环结束:
代码描述:

temp=取出元素3
循环 只要 当前元素值大于temp  并且 当前坐标>=0
	a[当前坐标+1]=a[当前坐标]
	当前坐标=当前坐标-1
循环结束
a[当前坐标+1]=temp

1.1.2进行第二次循环

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.1.3进行第三次循环

在这里插入图片描述

在这里插入图片描述

1.1.4进行第四次循环

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.1.5进行第五次循环

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
到此排序结束
代码描述:

外部循环:从1号元素到(长度-1)号元素
	temp=取出元素3
	循环 只要 当前元素值大于temp  并且 当前坐标>=0
		a[当前坐标+1]=a[当前坐标]
		当前坐标=当前坐标-1
	循环结束
	a[当前坐标+1]=temp
循环结束
排序结束

2.代码实现:

使用语言-python

def insertsort(nums):
	length=len(nums)#获得数组长度
	for i in range(1,length):#从1号元素到(长度-1)号元素
		temp=nums[i]#temp=取出元素
		j=i-1#记录内部循环开始坐标
		while j>=0 and nums[j]>temp:# 当前元素值大于temp  并且 当前坐标>=0
			nums[j+1]=nums[j]#a[当前坐标+1]=a[当前坐标]
			j-=1#当前坐标=当前坐标-1
		nums[j+1]=temp#a[当前坐标+1]=temp
	print(nums)#输出排序后的数组

3.时间复杂度

每次循环,插入到合适位置
同时,每次循环都会复制值给后面一个元素。

  • 最坏情况 每次进行i-1次赋值(每次都是插入到开始位置)
  • 最好情况,每次进行1次赋值(每次都是插入当前位置)

3.1 最好情况

此时,数组初始顺序为正序,如[1,2,3,4]。
外部循环为n-1次,每次循环进行1次复制 ,则共执行操作数=n-1 次,O( (n-1) )故时间复杂度如公式(3-1)所示。
O((n−1))=O(n)(3-1) O( (n-1) )=O( n) \tag {3-1}O((n1))=O(n)(3-1)

3.2最坏情况

此时,数组初始顺序为逆序,如[4,3,2,1]。
首次循环赋值n-1次 ,二次循环 赋值n-2 次,以此类推,有通项公式 如公式(3-2)所示、时间复杂度如公式(3-3)所示。
T=n−1+n−2+n−3+...+1+12∗(n−1)=n(n−1+1)+(n−1)2(3-2)T=n-1+n-2+n-3+...+1+\frac {1}{2}*(n-1)=\frac {n(n-1+1)+(n-1)}{2} \tag {3-2}T=n1+n2+n3+...+1+21(n1)=2n(n1+1)+(n1)(3-2)

O(T)=O(12(n2+n−1))≈O(n2)(3-3)O(T)=O(\frac{1}{2} (n^2+n-1))≈O(n^2) \tag {3-3}O(T)=O(21(n2+n1))O(n2)(3-3)

3.3 复杂度总结

综上所述,选择排序的时间复杂度如下表所示。

状态最好情况最坏情况平均时间复杂度
时间复杂度 O(n)\ O(n) O(n) O(n2)\ O(n^2) O(n2) O(n2)\ O(n^2) O(n2)

4.空间复杂度

选择排序是原地排序的一种排序,所以空间复杂度为O(1)

原地排序就是指在排序过程中不申请多余的存储空间,只利用原来存储待排数据的存储空间进行比较和交换的数据排序。

5.稳定性

假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。–百度百科

在上述的图表案例中,如果交换的条件: 只有 当前元素值大于temp 并且 当前坐标>=0,所以相同值的元素,可以保持相对位置。

6.算法优化

算法优化是指对算法的有关性能进行优化,如时间复杂度、空间复杂度、正确性、健壮性。由于算法应用情景变化很大,算法优化可以使算法具有更好泛化能力。

6.1 分析问题

优化的出发点是:循环的结束条件,如公式(6-1)所示:
j>=0       And      nums[j]>temp:(6-1) j>=0 ~~~~~~~And ~~~~~~ nums[j]>temp: \tag {6-1}j>=0       And      nums[j]>temp:(6-1)
每次循环都要判断是否到达数组边界,但这并非是必要的。

6.2 解决方案:

使用数组的初始位置记录temp值(设置监视哨),如下图所示

在这里插入图片描述这无需判断边界,只要判断nums[j]>temp 即可,但是代价是需要一个数组空间。

代码实现

# insertsort.py

#原始算法
def insertsort(nums):
	length=len(nums)
	for i in range(1,length):
		temp=nums[i]
		j=i-1
		while j>=0 and nums[j]>temp:
			nums[j+1]=nums[j]
			j-=1
		nums[j+1]=temp
	# print(nums)

#优化算法
def insertsort2(nums):
	length=len(nums)
	for i in range(2,length):
		nums[0]=nums[i]
		j=i-1
		while nums[j]>nums[0]:
			nums[j+1]=nums[j]
			j-=1
		nums[j+1]=nums[0]
	# print(nums[1:])

nums=[0,3, 2, 1, 8, 5, 4, 6]
import time 

start=time.clock()
for i in range(100000):
	insertsort(nums[1:])
print(f"原始执行100000次 用时{time.clock()-start}")

start=time.clock()
for i in range(100000):
	insertsort2(nums)
print(f"优化后执行100000次 用时{time.clock()-start}")

执行结果:

原始执行100000次 用时0.279714
优化后执行100000次 用时0.173260
[Finished in 0.5s]

由此可见,优化后,排序的执行速度有了明显提高。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值