1. 算法核心思想
将数组中所有的元素分别和前面已经排序好的元素进行比较,如果后面的元素比已排序的元素小,则交换位置,直至比较完成。
2. 具体实现逻辑
2.1 for
arr = [1, 22, -1, 9, 23, 5]
将数组分成两部分:有序部分和无序部分
第一步:数组第一个元素为有序部分
有序部分[1]
无序部分[22, -1, 9, 23, 5]
第二步:取无序部分的第一个元素,与有序部分的元素作比较, 如果无序部分的元素小,则交换位置
有序部分[1, 22]
无序部分[-1, 9, 23, 5]
第三步:重复第二步
有序部分[-1, 1, 22]
无序部分[9, 23, 5]
第四步:重复第二步
有序部分[-1, 1, 9, 22]
无序部分[23, 5]
第五步:重复第二步
有序部分[-1, 1, 9, 22, 23]
无序部分[5]
第六步:重复第二步
有序部分[-1, 1, 5, 9, 22]
无序部分[]
def insertSort(arr):
#默认数组第一个元素为有序部分,从第二个元素开始取
for i in range(1,len(arr)):
#arr[i]为无序部分元素
#arr[:i]为有序部分
#arr[i:]为有序部分
for j in range(i,0,-1):
if arr[j]<arr[j-1]:
arr[j],arr[j-1] = arr[j-1],arr[j]
else:
break
return arr
arr = [1, 22, -1, 9, 23, 5]
print(insertSort(arr))
2.2 while
首先用一个临时变量记录待插入的元素的值
temp=arr[i],然后比较
if temp<要比较的元素(来源于有序部分)
将要比较的元素往后挪,给temp腾位置
if temp>要比较的元素:break
def insertSortTwo(arr):
for i in range(1,len(arr)):
temp = arr[i]
j = i-1
while j>=0:
if temp<arr[j]:
arr[j+1] = arr[j]
j -= 1
else:
break
arr[j+1] = temp
return arr
arr = [1, 22, -1, 9, 23, 5]
print(insertSortTwo(arr))
3. 时间复杂度分析
- 最好的情况,即序列已经是一个有序序列,每次比较内层循还执行一次就退出,则总的比较次数是n-1次,时间复杂度是O(n)
- 最坏的情况,即每次比较内层循环都要比较到第一个元素,则第一次循环比较了1次,第二次循环比较了2次…第n-1次循环比较了n-1次,则总的比较次数是n(n-1)/2,时间复杂度是O(n2)
4. 优缺点分析
- 在大多数元素已经有序的情况下,插入排序的工作量较小
- 在元素数量较少的情况下,插入排序的工作量较小,插入排序的工作量和n的平方成正比,如果n比较小,那么排序的工作量自然要小得多。
- 插入排序是一种稳定排序。
5. 插入排序的稳定性
相同的元素在排序后没有发生位置的变化,称为稳定性
相同的元素在排序后交换了位置,就是不稳定
6. 稳定性的意义
实际工作中,排序算法肯定不会根据数据的一个属性来排序
举例:双11,淘宝订单,按照付款金额和付款时间排序,交易金额的前100位送优惠券
如果有相同的付款金额,按照付款时间来决定
当按照付款金额排序好后,再按照付款时间排序时,不能将付款时间相同的两个订单交换位置,否则会改变付款金额的顺序