冒泡排序逻辑:
1、对于一个无序的列表,可以不断遍历它,对比相邻的2个数,如果左边的数比右边大,则交换2个数的位置,多次遍历后,小的数会不断被交换到前面,大的数会不断交换到后面,最后完成排序。
2、假设列表有n个数字,最多也就是遍历n-1次,因为就算最小值排在第最后一位,它最多也只需要移动n-1次,就能排在第1位。
为什么称为冒泡排序
每一次遍历列表后,最大的数字都会被顶到最后面。如果我们把这个列表竖着放,这个过程看起来就是大的数字不断往上冒起来,所以称为冒泡排序。
过程详解
如下图所示:
第1次遍历结果:3比2大,交换;7比1天,交换,7比5大,交换,7比4大,交换 。最后9最大, 被放到最后。
可以发现1个规律:
第一次遍历时,当前整个列表都是无序区,无论最大值9在哪个位置,遍历后都会被顶到最后面;
第二次遍历开始前,已经可以确认,9已经不用参与对比了,所以无序区其实就是除了最后一个数之外的其他教字。
因此,每次遍历后,无序区会减少一个数,有序区会增加一个数;
粗略写法
def bubble_sort(li):
print('初始列表:%s'%li)
for i in range(len(li)-1): # 控制遍历的次数,最多遍历n-1次
for j in range(len(li)-i-1):
# 每次遍历,最大值会被顶到最后,意味着无序区减小一个数
if li[j] > li[j+1]:
li[j], li[j+1]= li[j+1], li[j]
print(li)
li = [3, 2, 7, 1, 5, 0, 4, 6, 9, 8]
bubble_sort(li)
优化方向
下图可以发现,后面几次其实都没有发生交换,当一次遍历后发现,并没有发生过交换,这时候我们可以认为排序已经完成,结束。
优化写法
def bubble_sort2(li):
print('初始列表:%s' % li)
for i in range(len(li) - 1): # 控制遍历的次数,最多遍历n-1次
has_exchange = False # 标识一次遍历是否发生交换,默认没有
for j in range(len(li) - i - 1):
# 每次遍历,最大值会被顶到最后,意味着无序区减小一个数
if li[j] > li[j + 1]:
li[j], li[j + 1] = li[j + 1], li[j]
has_exchange = True
if not has_exchange:
# 如果有一次遍历没有发生过一次交换,就不再遍历
break
print(li)
li = [3, 2, 7, 1, 5, 0, 4, 6, 9, 8]
bubble_sort2(li)