排序算法之冒泡排序(关键词:数据结构/算法/排序算法/冒泡排序)

本文深入探讨了冒泡排序算法,包括基本原理、详细解释和改进版算法。通过外层循环 n-1 轮,每次将最大元素冒泡到数列末尾,直至完成排序。对于已有序的数列,改进的冒泡排序能有效减少时间复杂度至 O(n)。文章还分析了算法的时间和空间复杂度,并指出冒泡排序的稳定性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

假定:有 1 个乱序的数列 nums ,其中有 n 个数。
要求:排好序之后是 从小到大 的顺序。

冒泡排序算法

代码

from swap import swap

def bubble_sort(nums):
	n = len(nums)

	for i in range(n-1):
		j = 1
		while j <= n-i-1:
			if nums[j-1] > nums[j]:
				swap(nums, j-1, j)
			j += 1

(对外层循环的循环次数range(len(nums)-1)的解释:
range(n-1)[0, 1, 2, 3, ..., n-2],共 n-1 个数;

如果有 1 个数,
则需要 0 轮外层循环,即无需排序;

如果有 2 个数,
则需要 1 轮外层循环;

如果有 3 个数,比如 [3, 2, 1],
第 0 轮外循环之后,数列为 [2, 1, 3],
第 1 轮外循环之后,数列为 [1, 2, 3],
则需要 2 轮外层循环;

。。。

如果有 n 个数,
则需要 n-1 轮外层循环。

原理

第 i 次循环中,对从第 0 到第 n-i-1 个元素从前往后进行比较,每次比较相邻的两个元素,如果前一个元素大于后一个元素,则两者互换位置,否则保持位置不变。整个过程一共进行 n-1 次循环,直到第 1 个和第 2 个元素完成比较完成,最终剩余最小的元素,留在第 1 个位置上,排序结束。

详细解释

第 0 轮排序:( i 等于 0)
第 0、1 个数比较大小,较大的数放到第 1 个位置;
。。。
第 j、j+1 个数比较大小,较大的数放到第 j+1 个位置;
。。。
第 n-2、n-1 个数比较大小,较大的数放到第 n-1 个位置。
第 0 轮排序完毕,第 1 大的数被放到数列的最后的位置,即第 n-1 个位置。

第 1 轮排序完毕,第 2 大的数被放到数列的最后的位置,即第 n-2 个位置。

第 2 轮排序完毕,第 3 大的数被放到数列的最后的位置,即第 n-3 个位置。

。。。

第 i 轮排序完毕,第 i+1 大的数被放到数列的最后的位置,即第 n-i-1 个位置。

。。。

第 n-1 轮排序:( i 等于 n-1)
。。。
第 n-1 轮排序完毕,第 n 大的数被放到数列的最后的位置,即第 0 个位置。

改进的冒泡排序算法

代码

def bubble_sort_better(nums):
	n = len(nums)

	for i in range(n-1):
		
		flag = False
		# flag 用于标记内层循环中,是否发生了交换。		
		j = 1
		while j <= n-i-1:
			if nums[j-1] > nums[j]:
				swap(nums, j-1, j)
				flag = True	# 发生了交换。
			j += 1

		if flag==False:	break
		# 若未发生交换,则说明数列初始状态是从小到大排列的,即有序的。

原理

最初的冒泡排序算法中,如果遇到最好的情况,即数列是有序(从小到大)的,仍然会走完所有的内外循环,时间复杂度为 O(n^2),但显然是不必要的,因此加入了 flag 标志,用于判断是否发生了交换。

如果初始数列就是从小到大排列的,则第 0 次进入外循环时,每 1 个内循环均不会改变 flag 的值,离开内循环后,flag 仍然为 False,break 跳出循环。

算法复杂度

时间复杂度:
最坏情况(初始数列为从大到小,逆序排列)时间复杂度为 O(n^2);
最好情况(初始数列为从小到大,顺序排列),只进入 1 次外循环,内循环约 n 次,时间复杂度为 O(n)。
平均时间复杂度为 O(n^2)。

空间复杂度:
冒泡排序只需要常数个额外空间用于保存中间变量,空间复杂度为 O(1)。

稳定性

从代码中,可以看出,如果 2 个相邻的数是相等的,则不做交换,即相对位置不会发生变化。
因此,冒泡排序是稳定的。

参考文献:

  1. 《数据结构(第 2 版)》 - 浙江大学 - 7.4.1 冒泡排序 - P271,P272;
  2. https://github.com/henry199101/sort/blob/master/bubble_sort.py。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值