目 录
1. 冒泡排序描述
1.1 冒泡排序实现原理
冒泡排序是指从第一个元素开始,依次和周边的元素做比较,如果后面的元素比前面的小,则两者进行交换,这样两两比较和交换一轮,则最后的元素即第n个元素 就是最大的,下次只需要交换到第 n-1 个元素即可。
这种行为有点类似于水中的气泡缓缓往上升到水面的过程,所以叫冒泡排序。
1.2 冒泡排序性能
性能指数 | 描述 | |
---|---|---|
时间复杂度(平均) | o(n2),即o(n**2) | 在一般乱序的情况下,每轮需要比较 n 个元素和交换 m(m<n)个元素。 |
时间复杂度(最好) | o(n) | 假如插入排序是正序的情况,那么优化过该算法可以得到这个最好的时间复杂度。 |
时间复杂度(最差) | o(n2),即o(n**2) | 假如插入排序是倒序的情况,虽然比较的时间少了,但是挪动元素的时间是最多的,挪动比比较更花时间。 |
空间复杂度 | o(1) | 只需要有限的几个变量 |
是否稳定 | 稳定 | 在比较的过程中,当两个相同大小的元素相邻,只比较大或者小,所以相等的时候是不会交换位置的。而当两个相等元素离着比较远的时候,也只是会把他们交换到相邻的位置。他们的位置前后关系不会发生任何变化,所以算法是稳定的。 |
2. 冒泡排序实现
2.1 冒泡排序简单实现
代码实现如下:
# 比较原始的冒泡排序方法
def Bubble_sort(nums):
nums_len=len(nums)
i=0
while(i<nums_len-1):
k=0
while(k<nums_len-i-1):
if(nums[k]>nums[k+1]):
nums[k],nums[k+1]=nums[k+1],nums[k]
k+=1
print(nums)
i+=1
print(i)
return(nums)
下面是测试代码
import random
example=list(range(20))
random.shuffle(example)
print("*"*100)
print(example)
print("*"*100)
res=Bubble_sort(example)
print("*"*100)
print(res)
测试代码运行结果如下:
从测试代码的运行结果可以看出,此代码一共循环了 n-1 次,依次将第 n 个、第 n-1 个、第 n-2 个、第 n-3 个最大的元素放到相应的位置。
2.2 冒泡排序优化-减少冒泡循环次数
如果修改一下待排序的数组,从下面的运行结果可以看出,在最后的 6 次循环里面,其实并没有进行任何交换,因为在前 n-2 次交换中都已经排好序了,这 6 次交换是没有意义的。
所以我们可以在此处进行一下优化,只有这一轮进行过交换,才会有下一轮,否则循环中止。这会很大程度的提高排序性能。 这样在非降序的情况下,可以实现最好的排序性能。
实现代码如下:
# 优化后的 Bubble Sort 算法
# 如果上一轮有过交换,才会继续循环
def Bubble_sort(nums):
nums_len=len(nums)
i=0
while(i<nums_len-1):
k=0
flag=False # flag 用于显示是否有交换
while(k<nums_len-i-1):
if(nums[k]>nums[k+1]):
nums[k],nums[k+1]=nums[k+1],nums[k]
flag=True #产生了交换,flag 设置为 True
k+=1
if(not flag):
break
print(nums)
i+=1
print(i)
return(nums)
使用相同的测试代码:
example=[10, 18, 16, 13, 1, 11, 4, 14, 8, 15, 12, 19, 2, 0, 3, 9, 17, 6, 5, 7]
print("*"*100)
print(example)
print("*"*100)
res=Bubble_sort(example)
print("*"*100)
print(res)
测试代码运行结果如下:
可以看到不必要的循环次数已经被取消了。
2.3 冒泡排序优化-减少每个循环中比较的次数
# 我们除了可以设置一个标志位,来表示当前数组已经完成排序
# 还可以记录一下上一次排序时候最后依次交换发生的地址,记成 end
# 这样下次循环时候,只需要循环到 end 即可,实现代码如下:
# 我们除了可以设置一个标志位,来表示当前数组已经完成排序
# 还可以记录一下上一次排序时候最后依次交换发生的地址,记成 end
# 这样下次循环时候,只需要循环到 end 即可,实现代码如下:
def Bubble_sort2(nums):
nums_len=len(nums)
i=0
last_end=nums_len-1
while(i<nums_len-1):
k=0
flag=False # flag 用于显示是否有交换
end=last_end
print("end is ==>",end)
while(k<end):
if(nums[k]>nums[k+1]):
nums[k],nums[k+1]=nums[k+1],nums[k]
flag=True #产生了交换,flag 设置为 True
last_end=k
k+=1
if(not flag):
break
print(nums)
i+=1
return(nums)
测试代码如下:
import random
nums=list(range(12))
random.shuffle(nums)
print(nums)
print("*"*80)
print(Bubble_sort2(nums))
运行结果如下:
可以看到,这样就少比较了1一个元素。