冒泡排序,是最经典的排序算法。下面从以下几个方面介绍该算法。
- 算法原理[algorithm principle]
- 算法实现[algorithm implementation]
- 时间复杂度[time complexity]
- 空间复杂度[space complexity]
- 稳定性[stability]
- 算法优化[Algorithm optimization]
1.算法原理
就像他的名字一样,就是像气泡一样的,从数组的底部互相交换数值,保证大数值在上。下面举个例子。
如有数组 array=[1,3,2,7,9,5]
下面进行第一次循环
从开始位置判断两个相邻位置大小,保证 array[j]<array[j+1]
=
满足 array[j]<array[j+1],不用进行交换。
由于3>2 所以进行交换,交换后,继续向下移动。
满足 array[j]<array[j+1],不用进行交换。
由于9>7 所以进行交换,交换后,继续向下移动。
由于9>5 所以进行交换,完成第一轮循环,将最大值9设置为灰色。
到此第一轮循环就完成了。代码描述如下。
从0到(数组长度-外侧循环数-1 ):#此时外侧循环为0(第一次循环外层循环数为0 ,因为数组从0开始)
如果 a[j]>a[j+1] 交换 a[j]>a[j+1]
否则 不做操作
下面进行第二次循环
满足 array[j]<array[j+1],不用进行交换。
满足 array[j]<array[j+1],不用进行交换。
满足 array[j]<array[j+1],不用进行交换。
7
由于7>5 所以进行交换,将7置为灰色,第二次循环结束。
到此第二轮循环就完成了。代码描述如下。
从 0 到数组长度-2, 循环:#由于9已经不用在比较,可以减少一次
如果 a[j]>a[j+1] 交换 a[j]>a[j+1]
否则 不做操作
下面进行第三次循环。(聪明的观众已经发现了,这个数组已经有序了,但是还是要继续循环。)
满足 array[j]<array[j+1],不用进行交换。
满足 array[j]<array[j+1],不用进行交换。
以此类推,我们就可以,这样…
我们就得到如下数组。
代码描述为
外层循环:从0到(数组长度-1):#表示循环次数
内层循环:从0到(数组长度-外侧循环数-1)
如果 a[j]>a[j+1] 交换 a[j]>a[j+1]
否则 不做操作
2. 算法实现
使用语言-python
def bubblesort(nums):
length=len(nums)
for i in range(length):
for j in range(0,length-i-1):
if nums[j]>nums[j+1]:
nums[j+1],nums[j]=nums[j],nums[j+1]#交换两个值
'''
#也可以写成经典交换方式
temp=nums[j]
nums[j]=nums[j+1]
nums[j+1]=temp
#或者使用异或交换
nums[j+1]=nums[j+1]^nums[j]
nums[j]=nums[j+1]^nums[j]
nums[j+1]=nums[j+1]^nums[j]
'''
print(nums)
3.时间复杂度
外层循环:从0到(数组长度-1):#表示循环次数
内层循环:从0到(数组长度-外侧循环数-1)
如果 a[j]>a[j+1] 交换 a[j]>a[j+1]
否则 不做操作
首次循环n-1
下一次 n-2
…
根据通项公式有T
T
=
n
−
1
+
n
−
2
+
n
−
3
+
.
.
.
+
1
=
n
(
n
−
1
+
1
)
2
=
n
2
2
T=n-1+n-2+n-3+...+1=\frac {n(n-1+1)}{2}=\frac {n^2}{2}
T=n−1+n−2+n−3+...+1=2n(n−1+1)=2n2
所以时间复杂度为
O
(
T
)
=
O
(
1
2
n
2
)
O(T)=O(\frac{1}{2} n^2)
O(T)=O(21n2)
4.空间复杂度
冒泡排序是原地排序的一种排序,所以空间复杂度为O(1)
原地排序就是指在排序过程中不申请多余的存储空间,只利用原来存储待排数据的存储空间进行比较和交换的数据排序。
5.稳定性
假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。–百度百科
冒泡排序是相邻的两个元素比较,交换也发生在这两个元素之间。如果两个元素相等,不用进行交换,所以排序前后相同元素的前后位置不会发生变化 ,所以冒泡排序是一种稳定排序算法。
6. 算法优化
还是以上述数组为例
当进行两次循环之后
明显排序已经结束了,但是循环还没有结束,还是会继续执行,这无疑是徒劳的。这是我们优化的出发点。
我们可以设置一个标记,如果一次循环内,没有发生交换,则结束循环。
def bubblesort2(nums):
length=len(nums)
for i in range(length):
flag=0#每次循环,将flag 设置为0
for j in range(0,length-i-1):
if nums[j+1]<nums[j]:
flag=1#如果发生交换,将flag 设置为1
nums[j+1],nums[j]=nums[j],nums[j+1]
if flag==0: break #若flag 还是0 表示未发生交换
print(nums)
到此结束 打完收工。