python-冒泡排序

1. 功能实现

"""
冒泡排序
	概述:
		是一种交换排序, 相邻两个数比较, 如果前面的数比后面的数大, 就交换位置(由小到大排序时)
	简介:
		在冒泡排序过程中, 每一轮比较出一个最大的数放在队列的最后, 若使用m表示元素的总数, 那么每次冒泡排序需要执行 m-1 轮; n表示已经进行过的轮数, 则每轮需要比较 m-n-1 次, 所以冒泡排序的平均时间复杂度和最坏时间复杂度都是O(n²)
	优点:
		稳定, 空间复杂度低, 简单易懂
"""
def bubbleSort(num_list):
    # 外层for循环控制要比较的轮数, 共需要执行 "长度-1" 次
    for i in range(len(num_list) - 1):
        # 内层for循环控制每一轮要比较的次数, 共需要执行 "长度-已执行的轮数-1" 次
        for j in range(len(num_list) - i - 1):
            print(f'第 {i + 1} 轮 第 {j + 1} 次 比较', end='\t')
            # 如果前面的数比后面的数大, 就交换位置
            if num_list[j] > num_list[j + 1]:
                print(f'{num_list[j]}{num_list[j + 1]} 交换位置', end='')
                num_list[j], num_list[j + 1] = num_list[j + 1], num_list[j]
            else:
                print(f'{num_list[j]}{num_list[j + 1]} 不交换位置', end='')
            print(num_list)
        print(f'第 {i + 1} 轮排序结果: {num_list}')


if __name__ == '__main__':

    num_list = [7, 6, 3, 9, 1, 8]
    print(f'排序前的数组顺序: {num_list}')
    bubbleSort(num_list)
    print(f'排序后的数组顺序: {num_list}')

控制台输出

排序前的数组顺序: [7, 6, 3, 9, 1, 8]
第 1 轮 第 1 次 比较	7 和 6 交换位置[6, 7, 3, 9, 1, 8]
第 1 轮 第 2 次 比较	7 和 3 交换位置[6, 3, 7, 9, 1, 8]
第 1 轮 第 3 次 比较	7 和 9 不交换位置[6, 3, 7, 9, 1, 8]
第 1 轮 第 4 次 比较	9 和 1 交换位置[6, 3, 7, 1, 9, 8]
第 1 轮 第 5 次 比较	9 和 8 交换位置[6, 3, 7, 1, 8, 9]
第 1 轮排序结果: [6, 3, 7, 1, 8, 9]
第 2 轮 第 1 次 比较	6 和 3 交换位置[3, 6, 7, 1, 8, 9]
第 2 轮 第 2 次 比较	6 和 7 不交换位置[3, 6, 7, 1, 8, 9]
第 2 轮 第 3 次 比较	7 和 1 交换位置[3, 6, 1, 7, 8, 9]
第 2 轮 第 4 次 比较	7 和 8 不交换位置[3, 6, 1, 7, 8, 9]
第 2 轮排序结果: [3, 6, 1, 7, 8, 9]
第 3 轮 第 1 次 比较	3 和 6 不交换位置[3, 6, 1, 7, 8, 9]
第 3 轮 第 2 次 比较	6 和 1 交换位置[3, 1, 6, 7, 8, 9]
第 3 轮 第 3 次 比较	6 和 7 不交换位置[3, 1, 6, 7, 8, 9]
第 3 轮排序结果: [3, 1, 6, 7, 8, 9]
第 4 轮 第 1 次 比较	3 和 1 交换位置[1, 3, 6, 7, 8, 9]
第 4 轮 第 2 次 比较	3 和 6 不交换位置[1, 3, 6, 7, 8, 9]
第 4 轮排序结果: [1, 3, 6, 7, 8, 9]
第 5 轮 第 1 次 比较	1 和 3 不交换位置[1, 3, 6, 7, 8, 9]
第 5 轮排序结果: [1, 3, 6, 7, 8, 9]
排序后的数组顺序: [1, 3, 6, 7, 8, 9]

1.1 发现问题

"""
	发现问题:
		当传入该序列时, 传入的序列在第一轮比较后, 排序就已经完成, 但是由于冒泡排序的总轮数未结束, 所以会继续比较下去, 浪费了资源 
	解决问题:
		可以在每一轮比较开始前设置一个标记, 如果交换位置则改变标记值, 每轮比较结束后判断标记是否被改变: 如果没有改变说明本轮比较未发生位置交换, 则排序结束
"""
if __name__ == '__main__':

	num_list = [6, 1, 2, 3, 4, 5]
	print(f'排序前的数组顺序: {num_list}')
    bubbleSort(num_list)
    print(f'排序后的数组顺序: {num_list}')

控制台输出

排序前的数组顺序: [6, 1, 2, 3, 4, 5]
第 1 轮 第 1 次 比较	6 和 1 交换位置[1, 6, 2, 3, 4, 5]
第 1 轮 第 2 次 比较	6 和 2 交换位置[1, 2, 6, 3, 4, 5]
第 1 轮 第 3 次 比较	6 和 3 交换位置[1, 2, 3, 6, 4, 5]
第 1 轮 第 4 次 比较	6 和 4 交换位置[1, 2, 3, 4, 6, 5]
第 1 轮 第 5 次 比较	6 和 5 交换位置[1, 2, 3, 4, 5, 6]
第 1 轮排序结果: [1, 2, 3, 4, 5, 6]
第 2 轮 第 1 次 比较	1 和 2 不交换位置[1, 2, 3, 4, 5, 6]
第 2 轮 第 2 次 比较	2 和 3 不交换位置[1, 2, 3, 4, 5, 6]
第 2 轮 第 3 次 比较	3 和 4 不交换位置[1, 2, 3, 4, 5, 6]
第 2 轮 第 4 次 比较	4 和 5 不交换位置[1, 2, 3, 4, 5, 6]
第 2 轮排序结果: [1, 2, 3, 4, 5, 6]
第 3 轮 第 1 次 比较	1 和 2 不交换位置[1, 2, 3, 4, 5, 6]
第 3 轮 第 2 次 比较	2 和 3 不交换位置[1, 2, 3, 4, 5, 6]
第 3 轮 第 3 次 比较	3 和 4 不交换位置[1, 2, 3, 4, 5, 6]
第 3 轮排序结果: [1, 2, 3, 4, 5, 6]
第 4 轮 第 1 次 比较	1 和 2 不交换位置[1, 2, 3, 4, 5, 6]
第 4 轮 第 2 次 比较	2 和 3 不交换位置[1, 2, 3, 4, 5, 6]
第 4 轮排序结果: [1, 2, 3, 4, 5, 6]
第 5 轮 第 1 次 比较	1 和 2 不交换位置[1, 2, 3, 4, 5, 6]
第 5 轮排序结果: [1, 2, 3, 4, 5, 6]
排序后的数组顺序: [1, 2, 3, 4, 5, 6]

2. 算法优化 1

def bubbleSortOptimize1(num_list):
    # 外层for循环控制要比较的轮数, 共需要执行 "长度-1"
    for i in range(len(num_list) - 1):
        # 设置标记
        sorted = True
        # 内层for循环控制每一轮要比较的次数, 共需要执行 "长度-已执行的轮数-1" 次
        for j in range(len(num_list) - i - 1):
            print(f'第 {i + 1} 轮 第 {j + 1} 次 比较', end='\t')
            # 如果前面的数比后面的数大, 就交换位置
            if num_list[j] > num_list[j + 1]:
                print(f'{num_list[j]}{num_list[j + 1]} 交换位置', end='')
                num_list[j], num_list[j + 1] = num_list[j + 1], num_list[j]
                # 发生位置交换, 说明排序未结束
                sorted = False
            else:
                print(f'{num_list[j]}{num_list[j + 1]} 不交换位置', end='')
            print(num_list)
        print(f'第 {i + 1} 轮排序结果: {num_list}')
        # 本轮位置未发生交换, 说明排序完成, 结束循环
        if sorted:
            return


if __name__ == '__main__':

	num_list = [6, 1, 2, 3, 4, 5]
	print(f'排序前的数组顺序: {num_list}')
    bubbleSortOptimize1(num_list)
    print(f'排序后的数组顺序: {num_list}')

控制台输出

排序前的数组顺序: [6, 1, 2, 3, 4, 5]
第 1 轮 第 1 次 比较	6 和 1 交换位置[1, 6, 2, 3, 4, 5]
第 1 轮 第 2 次 比较	6 和 2 交换位置[1, 2, 6, 3, 4, 5]
第 1 轮 第 3 次 比较	6 和 3 交换位置[1, 2, 3, 6, 4, 5]
第 1 轮 第 4 次 比较	6 和 4 交换位置[1, 2, 3, 4, 6, 5]
第 1 轮 第 5 次 比较	6 和 5 交换位置[1, 2, 3, 4, 5, 6]
第 1 轮排序结果: [1, 2, 3, 4, 5, 6]
第 2 轮 第 1 次 比较	1 和 2 不交换位置[1, 2, 3, 4, 5, 6]
第 2 轮 第 2 次 比较	2 和 3 不交换位置[1, 2, 3, 4, 5, 6]
第 2 轮 第 3 次 比较	3 和 4 不交换位置[1, 2, 3, 4, 5, 6]
第 2 轮 第 4 次 比较	4 和 5 不交换位置[1, 2, 3, 4, 5, 6]
第 2 轮排序结果: [1, 2, 3, 4, 5, 6]
排序后的数组顺序: [1, 2, 3, 4, 5, 6]

2.1 发现问题

"""
发现问题:
	通过分析执行结果, 在执行第一轮比较时, 从第三次比较开始便未发生任何位置交换, 说明后面的顺序已经排好了, 但是在第二轮比较时, 依然进行了后面的比较
解决问题:
	记录下最后一次发生位置交换的位置, 作为下一轮比较的最后位置
"""
if __name__ == '__main__':
    
    num_list = [1, 3, 2, 4, 5, 6]
    print(f'排序前的数组顺序: {num_list}')
    bubbleSortOptimize1(num_list)
    print(f'排序后的数组顺序: {num_list}')

控制台输出

排序前的数组顺序: [1, 3, 2, 4, 5, 6]
第 1 轮 第 1 次 比较	1 和 3 不交换位置[1, 3, 2, 4, 5, 6]
第 1 轮 第 2 次 比较	3 和 2 交换位置[1, 2, 3, 4, 5, 6]
第 1 轮 第 3 次 比较	3 和 4 不交换位置[1, 2, 3, 4, 5, 6]
第 1 轮 第 4 次 比较	4 和 5 不交换位置[1, 2, 3, 4, 5, 6]
第 1 轮 第 5 次 比较	5 和 6 不交换位置[1, 2, 3, 4, 5, 6]
第 1 轮排序结果: [1, 2, 3, 4, 5, 6]
第 2 轮 第 1 次 比较	1 和 2 不交换位置[1, 2, 3, 4, 5, 6]
第 2 轮 第 2 次 比较	2 和 3 不交换位置[1, 2, 3, 4, 5, 6]
第 2 轮 第 3 次 比较	3 和 4 不交换位置[1, 2, 3, 4, 5, 6]
第 2 轮 第 4 次 比较	4 和 5 不交换位置[1, 2, 3, 4, 5, 6]
第 2 轮排序结果: [1, 2, 3, 4, 5, 6]
排序后的数组顺序: [1, 2, 3, 4, 5, 6]

3. 算法优化 2

"""
进行两次冒泡排序优化:
	第一次 优化比较的轮数, 即减少外层for循环执行次数
	第二次 优化某一轮比较的次数, 即减少了内层for循环执行的次数
"""
def bubbleSortOptimize2(num_list):
    inner = range(len(num_list) - 1)
    # 外层for循环控制要比较的轮数, 共需要执行 "长度-1"
    for i in range(len(num_list) - 1):
        # 设置标记
        sorted = True
        # 内层for循环控制每一轮要比较的次数
        for j in inner:
            print(f'第 {i + 1} 轮 第 {j + 1} 次 比较', end='\t')
            # 如果前面的数比后面的数大, 就交换位置
            if num_list[j] > num_list[j + 1]:
                print(f'{num_list[j]}{num_list[j + 1]} 交换位置', end='')
                num_list[j], num_list[j + 1] = num_list[j + 1], num_list[j]
                # 发生位置交换, 说明排序未结束
                sorted = False
                # 记录一下最后交换的位置
                last_change = j
            else:
                print(f'{num_list[j]}{num_list[j + 1]} 不交换位置', end='')
            print(num_list)
        print(f'第 {i + 1} 轮排序结果: {num_list}')
        # 本轮位置未发生交换, 说明排序完成, 结束循环
        if sorted:
            return
        print(f'最后交换的位置: {last_change}')
        # 改变下一轮比较的范围
        inner = range(last_change)


if __name__ == '__main__':

    num_list = [1, 3, 2, 4, 5, 6]
    print(f'排序前的数组顺序: {num_list}')
    bubbleSortOptimize2(num_list)
    print(f'排序后的数组顺序: {num_list}')

控制台输出

排序前的数组顺序: [1, 3, 2, 4, 5, 6]
第 1 轮 第 1 次 比较	1 和 3 不交换位置[1, 3, 2, 4, 5, 6]
第 1 轮 第 2 次 比较	3 和 2 交换位置[1, 2, 3, 4, 5, 6]
第 1 轮 第 3 次 比较	3 和 4 不交换位置[1, 2, 3, 4, 5, 6]
第 1 轮 第 4 次 比较	4 和 5 不交换位置[1, 2, 3, 4, 5, 6]
第 1 轮 第 5 次 比较	5 和 6 不交换位置[1, 2, 3, 4, 5, 6]
第 1 轮排序结果: [1, 2, 3, 4, 5, 6]
最后交换的位置: 1
第 2 轮 第 1 次 比较	1 和 2 不交换位置[1, 2, 3, 4, 5, 6]
第 2 轮排序结果: [1, 2, 3, 4, 5, 6]
排序后的数组顺序: [1, 2, 3, 4, 5, 6]
  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值