介绍
冒泡排序(Bubble Sort)是一种简单的排序算法,其主要处理逻辑是通过重复比较和交换相邻的元素,将最大的元素逐渐“冒泡”到序列的末尾。
核心
- 比较的总轮数
- 每轮比较的总次数
- 谁和谁比较(交换)
处理步骤
具体的处理步骤如下:
- 初始状态:从序列的开始位置开始处理。
- 比较和交换:依次比较相邻的元素,如果它们的顺序错误(即前面的元素比后面的元素大),就交换这两个元素。
- 遍历:完成一轮比较和交换后,最大的元素会被移动到当前轮次的末尾。
- 减少比较范围:在每一轮排序后,可以减少需要比较的元素个数,因为每一轮结束时,最大的元素已经排到最后。
- 重复:重复上述步骤,直到没有需要交换的元素为止,说明序列已经排序完成。
冒泡排序的示例
示例 1:效率较低
# 定义冒泡排序方法
def bubble_sort(arr):
# 根据列表长度,计算需要进行排序的次数
n = len(arr)
# 循环执行指定的次数,因为 range 是从 0 开始,因此实际的循环次数等于列表的长度
for i in range(n - 1):
# 使用列表的索引值,从头开始,循环从列表中取相邻的两个值进行比较
for j in range(n - 1):
# 如果前一个值比后一个值大,就进行前后两个值的交换
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
if __name__ == '__main__':
list1 = [5, 3, 8, 4, 2]
bubble_sort(list1)
print(list1) # [2, 3, 4, 5, 8]
示例 2:示例 1 优化后
- 优化点 1:外层循环优化,若某次内循环没有发生任何交换,则说明已排完序,可提前退出循环
- 优化点 2:没经过一轮排序,最大的元素会被“冒泡”到最后,因此内层循环的比较范围可以逐步减少,不需要每次都遍历到列表的末尾
# 定义冒泡排序方法
def bubble_sort(arr):
# 计算列表的长度
n = len(arr)
# 外层循环控制排序轮次
for i in range(n - 1):
# 标志变量,检查是否发生过交换
swapped = False
# 内层循环比较相邻的元素,范围逐渐减小
for j in range(n - 1 - i):
# 如果前一个元素比后一个大,则交换
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
swapped = True # 发生了交换,标志为 True
# 如果一轮比较后没有交换,说明数组已排序好,提前退出
if not swapped:
break
# 主程序入口
if __name__ == '__main__':
list1 = [5, 3, 8, 4, 2]
bubble_sort(list1)
print(list1) # [2, 3, 4, 5, 8]
处理逻辑:
- 第一轮:
- 比较
5
和3
,交换得到[3, 5, 8, 4, 2]
- 比较
5
和8
,不交换 - 比较
8
和4
,交换得到[3, 5, 4, 8, 2]
- 比较
8
和2
,交换得到[3, 5, 4, 2, 8]
- 最大元素
8
已经排到最后。
- 比较
- 第二轮:
- 比较
3
和5
,不交换 - 比较
5
和4
,交换得到[3, 4, 5, 2, 8]
- 比较
5
和2
,交换得到[3, 4, 2, 5, 8]
- 末尾的
8
已经排好,继续处理前面的部分。
- 比较
- 第三轮:
- 比较
3
和4
,不交换 - 比较
4
和2
,交换得到[3, 2, 4, 5, 8]
- 末尾的
5
和8
已经排好,继续处理前面的部分。
- 比较
- 第四轮:
- 比较
3
和2
,交换得到[2, 3, 4, 5, 8]
- 经过这轮处理,所有元素已排序完成。
- 比较
时间复杂度
- 最坏情况:O(n²)(完全逆序时,每个元素都需要交换)
- 最优情况:O(n)(数据已经有序时,提前退出的机制将大幅提升性能)
- 平均情况:O(n²)
优缺点
- 优点:
- 实现简单
- 可以在原地排序,不需要额外的存储空间
- 缺点:
- 时间复杂度较高,不适合大规模数据排序
- 不稳定排序