Python 排序-插入排序-优化

本文介绍了Python中插入排序的优化,包括未优化版和使用二分查找的优化版,分析了时间复杂度。此外,还讲解了基于分治思想的希尔排序,讨论了希尔排序的步长计算和时间复杂度。文中通过实例代码展示了插入排序和希尔排序的过程,指出插入排序在性能上的优势。
摘要由CSDN通过智能技术生成

以下是本人学习极客时间的专栏《数据结构与算法之美》后,自己动手敲代码实现,并写下当时的思考,希望对你也有帮助。
系列文章:
工作后,为什么还要学习数据结构与算法
Python-排序-冒泡排序-优化
Python-排序-选择排序-优化

插入排序,我想你也并不陌生。可以简单地这样理解,插入排序就是就是往一个有序的数列中添中新的数据,插入之后保证数据列仍然有序,因此叫插入排序。

那么具体是如何实现的呢?要想保证插入后数据仍然有序,就需要先确定插入数据的位置。 首先我们将待排序的数据分为两个区间,有序区间和无序区间,初始的有序区间只包含一个元素,也就是数组的第一个元素,其他的就是无序区间;然后,依次从无序区间中选取一个元素,在有序区间找到合适的插入位置将其插入,并保证已排序区间的数据一直有序,最后重复这个过程,直到无序区间的元素为空,算法结束。

关键点:找到合适的位置插入前,需要先将插入位置后面的元素,按顺序往后移动,空出位置后再将新元素插入。

你可以先试着自己写写代码,练习 Python 编码的能力,不能眼高手低。下面是我写的未优化的插入排序算法

##未优化版插入排序

#encoding=utf-8
def insert_sort(data_list):
    '''
    无优化版
    '''
    count=0 #统计循环次数
    length = len(data_list)
    for i in range(1,length ): #默认第一个位置的元素是已排序区间,因此下标从 1 开始
        tmp = data_list[i] #待插入的数据
        j = i 
        while j > 0: #从已排序区间查找插入位置
            count +=1
            if tmp < data_list[j-1]:
                data_list[j] = data_list[j-1]  #元素向后移动,腾出插入位置
            else:
                break
            j -= 1
        data_list[j] = tmp #插入操作
        print(data_list)
    print(f"总循环次数为 {count}")
    return data_list

上述代码中的 count 只是为了统计循环次数,目的是和优化版的进行对比,当然您也可以对时间复杂度进行分析来对比性能的差异。 print(data_list) 是为了打印出每一次插入后数据列的结果,您可以对比结果来理解插入排序算法。

我们先找一组数据试跑下:

if __name__ == "__main__":
    unsort = [1,3,4,2,1,5,6,7,8,4]
    print(*insert_sort(unsort)) 

执行结果如下所示:

[1, 3, 4, 2, 1, 5, 6, 7, 8, 4]
[1, 3, 4, 2, 1, 5, 6, 7, 8, 4]
[1, 2, 3, 4, 1, 5, 6, 7, 8, 4]
[1, 1, 2, 3, 4, 5, 6, 7, 8, 4]
[1, 1, 2, 3, 4, 5, 6, 7, 8, 4]
[1, 1, 2, 3, 4, 5, 6, 7, 8, 4]
[1, 1, 2, 3, 4, 5, 6, 7, 8, 4]
[1, 1, 2, 3, 4, 5, 6, 7, 8, 4]
[1, 1, 2, 3, 4, 4, 5, 6, 7, 8]
总循环次数为 18
1 1 2 3 4 4 5 6 7 8

###性能分析

  • 空间复杂度:除了运行时需要一个临时变量存储交换的数据和下标,不需要额外的存储空间,因此空间复杂度是O(1),是原地排序算法。
  • 稳定性:对于值相同的元素,我们可以选择将后面出现的元素,插入到前面出现元素的后面,这样就可以保证原有的前后顺序不变,因此是一种稳定的排序算法。
  • 时间复杂度:如果数据是有序的,我们不需要搬移任何数据,在查找插入位置时,从尾到头在有序区间查找插入位置,每次只需要比较一次即可确定插入位置,因此最好的时间复杂度为O(n)。如果数据是倒序的,每次都相当于在数据的第一个位置插入新数据,所以需要移动大量的数据,最坏时间复杂度为O(n^2)。平时时间复杂度,由于数据中插入一个元素的平均时间复杂度为O(n),因此对于插入排序来说,每次插入操作都相当于在数组中插入一个数据,循环执行 n 次插入操作,所以平均时间复杂度为O(n^2)。

优化入口

当有序区间数据量很大时,查找数据的插入位置就会显得非常耗时,插入排序算法每次都是从有序区间查找插入位置,以此为切入点,我们可以使用二分查找法来快速确认待插入的位置,于是就有了优化版的插入排序算法,也叫二分查找插入算法。

##优化版插入排序

def insert_sort2(data_list):
    '''
    使用二分查找函数确定待插入元素在有序区间的插入位置
    '''
    count=0 #统计循环次数
    length = 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值