思想:循环遍历元素,把最大的放到最后面,或者把最小的放在最后面,这样遍历,若有n个元素,
第一个元素要比较n次,第二个元素要比较n-1次,所以我们只需构造这样一个场景即可。
通过冒泡原理的分析,冒泡排序次数m和元素比较次数j之间有如下关系:
冒泡排序次数m:1 2 3 4 5 6 7 8 范围是 for m in range(n)
元素比较次数j:8 7 6 5 4 3 2 1 范围是 for j in range(n-1,0,-1)
因为我们的冒泡排序只关心次数,所以冒泡排序次数m也可以写成 for m in range(n-1,0,-1),那么m和j效果就变成了:
冒泡排序次数m:8 7 6 5 4 3 2 1
元素比较次数j:8 7 6 5 4 3 2 1
问:为甚要关注j的排序呢?
因为j的值和元素比较的i是一一对应的
所以我们在获取冒泡排序次数m的时候,就可以直接把元素比较的次数j获取出来。
上代码:
def bubble_sort(alist):
"""实现冒泡排序的功能"""
# 列表的长度,元素的个数
n = len(alist)
# 确定冒泡排序的范围,比较次数都是递减的
for j in range(n - 1, 0, -1):
# 开始比较前,定义计数器count的值为0
count = 0
# 内层数据的比较范围
for i in range(j):
# 逐个比较确保最大的元素放到最右面
if alist[i] > alist[i + 1]:
alist[i], alist[i + 1] = alist[i + 1], alist[i]
# 数据替换完毕,计数器加1
count += 1
# 如果当前循环结束,但是count的值为0,没有加1,说明已经完成排序,那么结束当前循环
if count == 0:
break
return alist
if __name__ == "__main__":
alist = [9, 8, 7, 6, 6, 5, 4, 3, 2, 2, 1]
# 原来的列表
print("原来的列表:",alist)
bubble_sort(alist)
print("排序后的列表:",alist)
代码执行结果如下:
原来的列表: [9, 8, 7, 6, 6, 5, 4, 3, 2, 2, 1]
排序后的列表: [1, 2, 2, 3, 4, 5, 6, 6, 7, 8, 9]
时间复杂度
最优时间复杂度:O(n)
对于一个有序队列来说,内部只需要进行一次全内容遍历,就退出,内部的比较循环时间复杂度是O(n)。
对于冒泡循环,只进行了一次,所以冒泡循环的时间复杂度是O(1)
对于整体来说:最优时间复杂度就是 O(n)
最坏时间复杂度:O(n2)
最坏不过每次冒泡循环的元素比较,需要全部进行比较替换,所以每一次元素比较循环都是O(n)
那么对于总体来说,内外都是O(n),所以最坏的时间复杂度是O(n2)
稳定性:稳定
拓展:
改那个地方,结果是降序?
if alist[i] > alist[i + 1] 代码中的 > 改为 <
本节内容小结:
1、冒泡排序原理:相邻比较,大移后,数比较,大至底,数冒泡,小顺大。
2、冒泡排序实践步骤:大小比较-内部比较循环-外部冒泡循环-异常考虑