冒泡排序就是将序列从前往后遍历,从第一个元素开始,依次与相邻的元素进行对比,若前一个元素的值大于后一个元素的值,则交换两个元素的位置,再继续与后一个元素进行对比,将较大的值逐渐向序列的尾部移动。最后得到一个有序的序列。
当遍历一次序列后,已经将序列中较大的值移动到了序列尾部,再次进行遍历序列时,就不用再与被移动到序列尾部的元素进行对比了,因为此时序列尾部的元素已经是序列中较大的元素了,并且是有序的。
例如:对序列 lst = [6, 3, 1, 7, 4, 2, 5, 10, 8, 9] 进行冒泡排序
第一次遍历:将序列中第一个较大的值移动至序列末尾
如上图,依次遍历每个索引对应的值是否大于下一个相邻索引对应的值,大于就交换两个索引对应的值,否则就保持不变,继续遍历下一个索引,直到将第一个较大的值移动到序列的末尾。
第二次遍历:将序列中第二个较大的值移动至序列倒数第二的位置
注意:在第二次遍历的时候,遍历次数要比第一次遍历少一次,因为第一次遍历,已经将序列中最大的元素移动到了序列末尾,所以就不需要再与最后一个元素进行对比了,因为不会发生元素的交换。
第一次遍历结束后得到的序列是:[3,1,6,4,2,5,7,8,9,10]
如上图,依次进行遍历,将序列中第二大的值移动到序列倒数第二的位置。
以此类推,遍历len(lst)-1次,就可以将序列变成一个升序排列的序列。
代码如下:
lst = [6, 3, 1, 7, 4, 2, 5, 10, 8, 9]
def BubbleSort(lst):
for i in range(len(lst)-1):
# 遍历序列的次数
for j in range(len(lst)-1-i):
# 遍历序列中的每个元素,与相邻元素进行对比
if lst[j] > lst[j+1]:
# 当前元素大于下一个元素,就交换两个元素的值
lst[j], lst[j+1] = lst[j+1], lst[j]
return lst
print(BubbleSort(lst)) # 输出:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
上述代码可以进行优化,当遍历2次后,序列已经是有序的了,此时就可以不用再继续遍历了,例如序列为[8, 2, 3, 5, 7, 6, 9],第一次循环遍历后,得到的序列是:[2, 3, 5, 7, 6, 8, 9],第二次循环遍历后得到的序列是:[2, 3, 5, 6, 7, 8, 9],此时已经是一个有序的序列了,就没有必要去循环6次了。
优化代码如下:
lst = [8, 2, 3, 5, 7, 6, 9]
# 可以设置一个变量is_sort,值为True,每循环一次,is_sort就赋值为True,
# 当两个元素进行交换位置的时候,说明进行了排序,则将is_sort赋值为False
def BubbleSort(lst):
# 控制循环遍历的次数,循环遍历的次数比列表的长度要少一次
for i in range(len(lst)-1):
is_sort = True
# 遍历每个元素,每循环遍历一次,需要遍历比较的元素就少一个
for j in range(len(lst)-1-i):
if lst[j] > lst[j+1]:
# 当前元素的值大于下一个元素的值,则交换两个元素的位置
lst[j], lst[j+1] = lst[j+1], lst[j]
is_sort = False
# print("遍历了%d次"%(i+1))
# print(lst)
# 当本次循环遍历完后,发现没有元素之间的调换位置,则说明排序已经完成,使用break结束循环
if is_sort:
break
return lst
print(BubbleSort(lst))
还可以再进行优化一次:当序列的后半部分本身就是有序的,那么每次循环遍历的时候,没有必要每次都去比较一次。
可以通过一个变量,去记录发生元素交换的位置,下一次循环遍历时,遍历元素就只遍历到发生元素交换的位置即可。例如lst = [2, 3, 1, 5, 6, 7, 8, 9],[5, 6, 7, 8, 9]已经是有序的了,可以不用每次都进行比较。
优化代码如下:
lst = [2, 3, 1, 5, 6, 7, 8, 9]
# 可以设置一个变量index,用来记录交换元素的位置,默认值为-1
# 当发生元素交换时,就将元素的索引赋值给index,下一次循环遍历时,就只遍历index索引前的元素
def BubbleSort(lst):
# 控制循环遍历的次数,循环遍历的次数比列表的长度要少一次
index = -1 # 记录发生元素两两交换的位置
for i in range(len(lst)-1):
is_sort = True # 记录是否有发生元素的交换
if index != -1: # 元素交换的位置不为-1
num = index # 就将index赋值给num(需要遍历的元素位置)
else: # 当index为-1,说明是进行第一次循环遍历
num = len(lst)-1-i
for j in range(num):
if lst[j] > lst[j+1]:
# 当前元素的值大于下一个元素的值,则交换两个元素的位置
lst[j], lst[j+1] = lst[j+1], lst[j]
is_sort = False # 元素进行交换了
index = j # 元素交换的位置
print(f"循环了{j+1}次")
print(lst)
print("遍历了%d次"%(i+1))
print(lst)
# 当本次循环遍历完后,发现没有元素之间的调换位置,则说明排序已经完成,使用break结束循环
if is_sort:
break
return lst
print(BubbleSort(lst))