冒泡排序(Bubble Sort),是一种比较排序算法,它通过重复遍历数列,比对和交换错误顺序的相邻元素实现对数列的排序。
原理
假设被排序数组 a 的长度为 n,冒泡排序首先比对尾部相邻元素 a[n-1] 和 a[n-2](假设数组索引从 0 开始),如果它们的顺序错误,则交换它们。之后,比较 a[n-2] 和 a[n-3] 并在顺序错误时交换它们,以此类推,直到 a[0] 被比对,此时最小(或最大)的数值被确定在 a[0] 位置。
此时,冒泡排序再次从 a[n-1] 和 a[n-2] 开始比对,如果它们的顺序错误,则交换它们,直到 a[1] 被比对,此时数列中第二小(或第二大)的数值被确定在 a[1] 位置。循环执行上述操作,直至 a[n-2] 位置的数值被确认,则数列完成排序。
综上,冒泡排序的操作步骤如下:
- 从尾部元素开始比较相邻两元素,若尾部元素小于相邻元素,则交换两元素位置。
- 向前对每对相邻元素做同样的比对和交换操作,从尾部第一对到头部最后一对,完成后,头部元素将成为数列中最小的元素。
- 重新从尾部开始做第 1、2 步操作,除去每次重复之前数列头部已排序的元素。
- 重复上述操作,直至没有任何一对元素需要比较。
以数列 (6, 2, 3, 1, 8) 为例,冒泡排序的执行过程如下所示:
第一次遍历:
第二次遍历:
第三次遍历:
第四次遍历:
实现
冒泡排序 Python 实现代码:
def bubbleSort(nums):
n = len(nums)
for i in range(1, n):
swapped = False
for j in range(n - 1, i - 1, -1):
if nums[j] < nums[j - 1]:
nums[j], nums[j - 1] = nums[j - 1], nums[j]
swapped = True
if swapped == False:
break
return nums
性能
根据冒泡排序的实现逻辑可知,外层循环执行 n − 1 n-1 n−1 次,内层循环执行 ( n − 1 ) − ( i − 1 ) = n − i (n-1)-(i-1) = n-i (n−1)−(i−1)=n−i 次,比较和交换操作为常数级 O ( 1 ) O(1) O(1)。因此,冒泡排序的时间复杂度可通过下式计算:
∑ i = 1 n − 1 ∑ j = i n − 1 1 = ∑ i = 1 n − 1 ( n − i ) = ( n − 1 ) + ( n − 2 ) + . . . + 1 = n ( n − 1 ) 2 \begin{aligned} \sum_{i=1}^{n-1}\sum_{j=i}^{n-1}1 &= \sum_{i=1}^{n-1}(n-i) \\ &= (n-1) + (n-2) + ... + 1 \\ &= \frac{n(n-1)}{2} \end{aligned} i=1∑n−1j=i∑n−11=i=1∑n−1(n−i)=(n−1)+(n−2)+...+1=2n(n−1)
因此,冒泡排序在最坏情况与平均情况下的时间复杂度均为 O ( n 2 ) O(n^2) O(n2),在最好情况下,数组有序,时间复杂度为 O ( n ) O(n) O(n)。
在空间复杂度方面,冒泡排序只需固定数量的额外空间用于存储数组长度、索引值和临时变量,所以空间复杂度为 O ( 1 ) O(1) O(1)。
在稳定性方面,冒泡排序只有在相邻元素值不相等且顺序错误时才对元素的位置进行调整,值相等元素的相对顺序不会发生变化,因此,冒泡排序是稳定的。