冒泡排序
原理
# 列表每两个相邻的数,如果前面的数比后面的大,则交换这两个数。
# 一趟排序完成后,则无序区减少一个数,有序区增加一个数。
# 每循环一趟,从无序区冒出来一个最大的数,放入有序区,最终得到一个升序的列表
# 代码关键点:趟、无序区范围
代码
# -*- coding: utf-8 -*-
# created by X. Liu on 2020/3/7
def bubble_sort(li):
n = len(li)
for i in range(n - 1): # i表示循环趟数,每循环一次,就冒出来一个最大的数
for j in range(n - 1 - i): # j表示每趟循环中需要前后比较两个数的次数
if li[j] > li[j+1]: # 只要前面的数比后面的数大,就交换位置
li[j+1], li[j] = li[j], li[j+1]
# 如果是逆序排序,只需将if判断的中的 '>' 修改为 '<'
代码解读
冒泡排序的时间复杂度:O(n^2)
# 趟:i指的是躺数,每循环一次就冒出来一个最大的数,所以一共需要循环len(li)-1次
# 无序区:每循环一趟,就会找到一个最大的数,有序的个数就会增加一个,无序区的个数就会减少一个。
# 那么每趟需要比较的次数,就是无序区长度-1;而无序区长度等于len(li)-1-i
动画演示
改进
对于上述的冒泡排序有可以优化的地方,如果一趟循环过程中没有发生交换,则说明这趟的所有数字已经是有序的,不需要再循环下面的趟数。
# -*- coding: utf-8 -*-
# created by X. Liu on 2020/3/7
def bubble_sort(li):
n = len(li)
for i in range(n - 1):
exchange = False # 记录本趟是否发生交换
for j in range(n - 1 - i):
if li[j] > li[j+1]:
li[j+1], li[j] = li[j], li[j+1]
exchange = True # 记录交换
if not exchange: # 如果没有交换,则已经有序,直接退出
return
测试
# 极端情况:只需一趟循环
def bubble_sort(li):
n = len(li)
for i in range(n - 1):
exchange = False # 记录本趟是否发生交换
for j in range(n - 1 - i):
if li[j] > li[j+1]:
li[j+1], li[j] = li[j], li[j+1]
exchange = True # 记录交换
print(li)
if not exchange: # 如果没有交换,则已经有序,直接退出
return
li = [1,2,3,4,5,6,7,8,9]
print(li)
bubble_sort(li)
# output:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]