冒泡排序(Bubble Sorting)
基本思想:通过对待排序序列从前向后(从下标较小的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部,就象水底下的气泡一样逐渐
向上冒。
因为排序的过程中,各元素不断接近自己的位置,如果一趟比较下来没有进行过交换,就说明序列有序,因此要在排序过程中设置一个标志flag判断元素是否进行过交换。从而减少不必要的比较。(这里说的优化,可以在冒泡排序写好后,在进行)
放一张图,请自行理解
这里画的就是冒泡的具体过程:
算法思路解析
这里使用一个实例来进行解释,这里有个无序数组arr[ 3,9,-1,0,-2 ]
第一遍比较:我们从第一个数开始,看第一个数是否比第二个数大:如果大于,则交换两者的位置,否则不进行任何操作。重复这个操作直到倒数第二个位置,也即是arr.length-1。通过这次比较我们找到了这个数组中最大的数9,它会冒泡一样的交换到数组的末尾。
arr[ 3,-1,0,-2,9 ]
第二遍比较:这次比较和第一遍几乎没有区别,唯一要改变是不在需要比较倒数第一个和倒数第二个了。
arr[ -1,0,-2,3,9]
第三遍比较:这里和上面一样,只是比较次数再少一次。
arr[-1,-2,0,3,9]
第四次比较:不解释了,自己总结。
arr[-2,-1,0,3,9]
到这里数组的排序操作已经结束了。你可以看出每次比较就是将当前需要比较部分的最大值通过交换的方式移动到数组的目前需要排序部分的末尾,每进行一次循环都相当于是增加了一个已经排好序的数字。
arr = [0 for i in range(8000)]
for i in range(8000):
arr[i]=random.randint(0,8000)
#基本的冒泡排序
def BubleSort(arr):
temp = 0
#总共要进行数组长度减1的大循环
for i in range(len(arr)-1):
#每次内循环都会冒出一个最小或者最大值,故下次循环比较次数-1
for j in range(len(arr)-1-i):
if arr[j]>arr[j+1]:
t=arr[j]
arr[j]=arr[j+1]
arr[j+1]=t
print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))
BubleSort(arr)
print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))
#输出结果
print("普通版的冒泡排序")
print(arr)
如果前面你已经理解了的话,请看一下上面的这个代码,如果条件允许。你可以在你的电脑上面运行它,你会发现当数据到达8000时,电脑使用冒泡排序的时间效率并不高,理论上讲冒泡排序的时间复杂度为O(n^2),在我的电脑上需要13秒左右才能得到结果。这个时间跟硬件条件有关,如果你的电脑条件更好,时间会更短。但是怎么在算法上进行改进呢?
冒泡排序优化
其实你会发现,如果数据本来及时有序的,或者部分有序,例如 1,2,3,4,5.其实我在遍历的时候就可以发现它没有一次进入交换语句,那么此时已经是有序数组。稍作修改后,代码如下:
arr2 = [0 for i in range(8000)]
for i in range(8000):
arr2[i]=random.randint(0,8000)
#冒泡排序优化
def BubleSort2(arr):
temp = 0
flag = False
#总共要进行数组长度减1的大循环
for i in range(len(arr)-1):
flag = False
#每次内循环都会冒出一个最小或者最大值,故下次循环比较次数-1
for j in range(len(arr)-1-i):
if arr[j]>arr[j+1]:
flag = True
t=arr[j]
arr[j]=arr[j+1]
arr[j+1]=t
#如果没有一次进入交换语句,说明后面的数字都已经有序
if flag == False:
break
print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))
BubleSort2(arr2)
print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))
print("优化后的冒泡排序")
print(arr2)
你可以在你的电脑上测试是否缩短了运行时间,不过我在自己的电脑上测试时,差距并不大。偶尔会缩短一秒的运行 时间,有时甚至没有区别。