python-插入排序

1. 直接插入排序

"""
直接插入排序:
    将需要排序的序列分成两个部分,前面部分是排序好的,后米部分是未排序的
    每轮从未排序的部分取出一个数,然后通过比较大小把它插入到前面部分制定位置,没插入一个数后,
    排序好的部分增加一个数,未排序的部分减少一个数,直到序列排序完成
时间复杂度:
    直接插入排序:最开始的第0个数可以认为是排序好的作为前面部分,
    后面部分只要从第一个数开始,每个数往前面序列中插入, 
    所以待排序的的序列一个m个元素, 则需要插入m-1次 每一次的插入操作需要比较若干次
    所以直接插入排序的平均时间复杂度和最坏时间复杂度都是O(n²)
"""

def insertSort(num_list):
    # 从第一个位置开始向后遍历
    for i in range(1, len(num_list)):
        # 将第 i 个数存入临时变量中
        temp = num_list[i]
        # 变量 j 用于记录和临时变量比较的位置, 从 i 的前一个位置开始比较
        j = i - 1
        # print(f'要插入的值 {temp}  第 {i} 次 插入排序')
        flag = True
        # 若 j 未超过范围且 第 j 个元素大于临时变量中的值
        while j >= 0 and num_list[j] > temp:
            # 将第 j 个元素向后移动一个位置
            num_list[j + 1] = num_list[j]
            print(f'发生位置移动 {j} -> {j + 1} 移动后的列表 {num_list}')
            # j-1 继续向前比较
            j -= 1
            flag = False

        # 将临时变量存入最后一个未移动的位置的后一个位置
        num_list[j + 1] = temp
        if not flag:
            print(f'要插入的值 {temp}  插入的位置 {j + 1} 插入后的列表 {num_list}')


if __name__ == '__main__':

    data_list = [7, 4, 3, 8, 0, 4, 3, 5, 1, 6]
    print(f'排序前的数组顺序: {data_list}')
    insertSort(data_list)
    print(f'排序后的数组顺序: {data_list}')

控制台输出

排序前的数组顺序: [7, 4, 3, 8, 0, 4, 3, 5, 1, 6]
发生位置移动 0 -> 1 移动后的列表 [7, 7, 3, 8, 0, 4, 3, 5, 1, 6]
要插入的值 4  插入的位置 0 插入后的列表 [4, 7, 3, 8, 0, 4, 3, 5, 1, 6]
发生位置移动 1 -> 2 移动后的列表 [4, 7, 7, 8, 0, 4, 3, 5, 1, 6]
发生位置移动 0 -> 1 移动后的列表 [4, 4, 7, 8, 0, 4, 3, 5, 1, 6]
要插入的值 3  插入的位置 0 插入后的列表 [3, 4, 7, 8, 0, 4, 3, 5, 1, 6]
发生位置移动 3 -> 4 移动后的列表 [3, 4, 7, 8, 8, 4, 3, 5, 1, 6]
发生位置移动 2 -> 3 移动后的列表 [3, 4, 7, 7, 8, 4, 3, 5, 1, 6]
发生位置移动 1 -> 2 移动后的列表 [3, 4, 4, 7, 8, 4, 3, 5, 1, 6]
发生位置移动 0 -> 1 移动后的列表 [3, 3, 4, 7, 8, 4, 3, 5, 1, 6]
要插入的值 0  插入的位置 0 插入后的列表 [0, 3, 4, 7, 8, 4, 3, 5, 1, 6]
发生位置移动 4 -> 5 移动后的列表 [0, 3, 4, 7, 8, 8, 3, 5, 1, 6]
发生位置移动 3 -> 4 移动后的列表 [0, 3, 4, 7, 7, 8, 3, 5, 1, 6]
要插入的值 4  插入的位置 3 插入后的列表 [0, 3, 4, 4, 7, 8, 3, 5, 1, 6]
发生位置移动 5 -> 6 移动后的列表 [0, 3, 4, 4, 7, 8, 8, 5, 1, 6]
发生位置移动 4 -> 5 移动后的列表 [0, 3, 4, 4, 7, 7, 8, 5, 1, 6]
发生位置移动 3 -> 4 移动后的列表 [0, 3, 4, 4, 4, 7, 8, 5, 1, 6]
发生位置移动 2 -> 3 移动后的列表 [0, 3, 4, 4, 4, 7, 8, 5, 1, 6]
要插入的值 3  插入的位置 2 插入后的列表 [0, 3, 3, 4, 4, 7, 8, 5, 1, 6]
发生位置移动 6 -> 7 移动后的列表 [0, 3, 3, 4, 4, 7, 8, 8, 1, 6]
发生位置移动 5 -> 6 移动后的列表 [0, 3, 3, 4, 4, 7, 7, 8, 1, 6]
要插入的值 5  插入的位置 5 插入后的列表 [0, 3, 3, 4, 4, 5, 7, 8, 1, 6]
发生位置移动 7 -> 8 移动后的列表 [0, 3, 3, 4, 4, 5, 7, 8, 8, 6]
发生位置移动 6 -> 7 移动后的列表 [0, 3, 3, 4, 4, 5, 7, 7, 8, 6]
发生位置移动 5 -> 6 移动后的列表 [0, 3, 3, 4, 4, 5, 5, 7, 8, 6]
发生位置移动 4 -> 5 移动后的列表 [0, 3, 3, 4, 4, 4, 5, 7, 8, 6]
发生位置移动 3 -> 4 移动后的列表 [0, 3, 3, 4, 4, 4, 5, 7, 8, 6]
发生位置移动 2 -> 3 移动后的列表 [0, 3, 3, 3, 4, 4, 5, 7, 8, 6]
发生位置移动 1 -> 2 移动后的列表 [0, 3, 3, 3, 4, 4, 5, 7, 8, 6]
要插入的值 1  插入的位置 1 插入后的列表 [0, 1, 3, 3, 4, 4, 5, 7, 8, 6]
发生位置移动 8 -> 9 移动后的列表 [0, 1, 3, 3, 4, 4, 5, 7, 8, 8]
发生位置移动 7 -> 8 移动后的列表 [0, 1, 3, 3, 4, 4, 5, 7, 7, 8]
要插入的值 6  插入的位置 7 插入后的列表 [0, 1, 3, 3, 4, 4, 5, 6, 7, 8]
排序后的数组顺序: [0, 1, 3, 3, 4, 4, 5, 6, 7, 8]

2. 希尔排序

"""
希尔排序:
    也称为缩小增量排序, 是插入排序的一种改进, 可以将后面较小的数快速的换到较靠前的位置,
    将待排序序列按照步长分为若干组, 每轮分别排序组内元素,一轮结束后,各组内的元素已经排序好
    然后再缩小步长重新分组排序,直到执行完步长为1后排序完成

时间复杂度:
    平均时间复杂度一般介于O(nlogn)到O(n^2)
    希尔排序通常比直接插入排序更快,尤其是在处理大规模数据时,因为它减少了元素之间的比较次数
"""

def shellSort(num_list):
    # 初始步长
    step = len(num_list) // 2
    # 遍历所有步长
    while step > 0:
        # 从每一组的第二个元素开始遍历, 初始值为当前组的第二个元素,即step值
        # 举例 本例10个元素 步长为 10 // 2 = 5 则 第一组中第二个元素为 4
        print(f'当前的步长为 {step}')
        for i in range(step, len(num_list)):
            # 临时变量用于存储第 i 个数
            temp = num_list[i]
            # 从本组中的前一个位置开始比较, 下表为 i - step
            j = i - step
            # print(f'要插入的值 {temp}  第 {i} 次 插入排序')
            flag = True
            # 遍历本组中前面所有元素, 若本组中前面的元素更大则交换位置
            while j >= 0 and num_list[j] > temp:
                num_list[j + step] = num_list[j]
                print(f'发生位置移动 {j} -> {j + step} 移动后的列表 {num_list}')
                # 改变下标 遍历本组中的前一个元素
                j -= step
                flag = False
            # 将临时变量放在交换后的位置
            num_list[j + step] = temp
            if not flag:
                print(f'要插入的值 {temp}  插入的位置 {j + step} 插入后的列表 {num_list}')
        # 继续缩小步长
        step //= 2


if __name__ == '__main__':

    data_list = [7, 4, 3, 8, 0, 4, 3, 5, 1, 6]
    print(f'排序前的数组顺序: {data_list}')
    shellSort(data_list)
    print(f'排序后的数组顺序: {data_list}')

控制台输出

排序前的数组顺序: [7, 4, 3, 8, 0, 4, 3, 5, 1, 6]
当前的步长为 5
发生位置移动 0 -> 5 移动后的列表 [7, 4, 3, 8, 0, 7, 3, 5, 1, 6]
要插入的值 4  插入的位置 0 插入后的列表 [4, 4, 3, 8, 0, 7, 3, 5, 1, 6]
发生位置移动 1 -> 6 移动后的列表 [4, 4, 3, 8, 0, 7, 4, 5, 1, 6]
要插入的值 3  插入的位置 1 插入后的列表 [4, 3, 3, 8, 0, 7, 4, 5, 1, 6]
发生位置移动 3 -> 8 移动后的列表 [4, 3, 3, 8, 0, 7, 4, 5, 8, 6]
要插入的值 1  插入的位置 3 插入后的列表 [4, 3, 3, 1, 0, 7, 4, 5, 8, 6]
当前的步长为 2
发生位置移动 0 -> 2 移动后的列表 [4, 3, 4, 1, 0, 7, 4, 5, 8, 6]
要插入的值 3  插入的位置 0 插入后的列表 [3, 3, 4, 1, 0, 7, 4, 5, 8, 6]
发生位置移动 1 -> 3 移动后的列表 [3, 3, 4, 3, 0, 7, 4, 5, 8, 6]
要插入的值 1  插入的位置 1 插入后的列表 [3, 1, 4, 3, 0, 7, 4, 5, 8, 6]
发生位置移动 2 -> 4 移动后的列表 [3, 1, 4, 3, 4, 7, 4, 5, 8, 6]
发生位置移动 0 -> 2 移动后的列表 [3, 1, 3, 3, 4, 7, 4, 5, 8, 6]
要插入的值 0  插入的位置 0 插入后的列表 [0, 1, 3, 3, 4, 7, 4, 5, 8, 6]
发生位置移动 5 -> 7 移动后的列表 [0, 1, 3, 3, 4, 7, 4, 7, 8, 6]
要插入的值 5  插入的位置 5 插入后的列表 [0, 1, 3, 3, 4, 5, 4, 7, 8, 6]
发生位置移动 7 -> 9 移动后的列表 [0, 1, 3, 3, 4, 5, 4, 7, 8, 7]
要插入的值 6  插入的位置 7 插入后的列表 [0, 1, 3, 3, 4, 5, 4, 6, 8, 7]
当前的步长为 1
发生位置移动 5 -> 6 移动后的列表 [0, 1, 3, 3, 4, 5, 5, 6, 8, 7]
要插入的值 4  插入的位置 5 插入后的列表 [0, 1, 3, 3, 4, 4, 5, 6, 8, 7]
发生位置移动 8 -> 9 移动后的列表 [0, 1, 3, 3, 4, 4, 5, 6, 8, 8]
要插入的值 7  插入的位置 8 插入后的列表 [0, 1, 3, 3, 4, 4, 5, 6, 7, 8]
排序后的数组顺序: [0, 1, 3, 3, 4, 4, 5, 6, 7, 8]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值