关于冒泡、选择、快速排序算法的Python实现代码,此处不赘述,完整代码请查看:
问题1:就这三种排序算法而言,快排是否是最优方案?
问题2:冒泡和选择的时间复杂度相同,其时间性能表现是否真的相同(或者相差无几)?
一、在数组的无序程度较高的情况下
下面直接比较它们的时间性能,代码如下:
if __name__ == '__main__':
import numpy
import time
t = time.time()
for i in range(10000):
array = list(numpy.random.randint(0, 100, 50))
t0 = time.time() - t
print('numpy生成50个0~100之间的数字,10000次所需时间:', t0, 's')
t = time.time()
for i in range(10000):
array = list(numpy.random.randint(0, 100, 50))
bubble_sort(array)
print('冒泡排序:', time.time() - t - t0, 's')
t = time.time()
for i in range(10000):
array = list(numpy.random.randint(0, 100, 50))
select_sort(array)
print('选择排序:', time.time() - t - t0, 's')
t = time.time()
for i in range(10000):
array = list(numpy.random.randint(0, 100, 50))
quick_sort(array)
print('快速排序:', time.time() - t - t0, 's')
10000次的50是数字的排序时间消耗,多次试验结果如下:
numpy生成50个0~100之间的数字,10000次所需时间: 0.18699336051940918 s
冒泡排序: 1.6431183815002441 s
选择排序: 0.7640233039855957 s
快速排序: 0.4690079689025879 s
numpy生成50个0~100之间的数字,10000次所需时间: 0.1920773983001709 s
冒泡排序: 1.551903486251831 s
选择排序: 0.7149889469146729 s
快速排序: 0.5479793548583984 s
numpy生成50个0~100之间的数字,10000次所需时间: 0.20493817329406738 s
冒泡排序: 1.5134046077728271 s
选择排序: 0.6773779392242432 s
快速排序: 0.4561192989349365 s
numpy生成50个0~100之间的数字,10000次所需时间: 0.1710827350616455 s
冒泡排序: 1.5479202270507812 s
选择排序: 0.7355144023895264 s
快速排序: 0.49486231803894043 s
结论:
1、虽然选择排序和冒泡排序的时间复杂度都是O(n^2),但是显然选择排序要优于冒泡排序,时间消耗大约是其1/2,大约节省50%的时间。
2、快速排序在这三个方法中表现最好,时间消耗大约是冒泡排序的1/3。
二、在数组为正序(从小到大排列)的情况下
if __name__ == '__main__':
import time
print([i for i in range(50)])
t = time.time()
for i in range(10000):
array = [i for i in range(50)]
t0 = time.time() - t
print('生成10000次数据所需时间:', t0, 's')
t = time.time()
for i in range(10000):
array = [i for i in range(50)]
bubble_sort(array)
print('冒泡排序:', time.time() - t - t0, 's')
t = time.time()
for i in range(10000):
array = [i for i in range(50)]
select_sort(array)
print('选择排序:', time.time() - t - t0, 's')
t = time.time()
for i in range(10000):
array = [i for i in range(50)]
quick_sort(array)
print('快速排序:', time.time() - t - t0, 's')
测试结果:
生成10000次数据所需时间: 0.012993097305297852 s
冒泡排序: 0.8310296535491943 s
选择排序: 0.6019954681396484 s
快速排序: 1.3461222648620605 s
生成10000次数据所需时间: 0.01307988166809082 s
冒泡排序: 0.8245120048522949 s
选择排序: 0.6059088706970215 s
快速排序: 1.3093125820159912 s
生成10000次数据所需时间: 0.012005090713500977 s
冒泡排序: 0.9179930686950684 s
选择排序: 0.6651043891906738 s
快速排序: 1.4826264381408691 s
总结:在正序(已排好序)的情况下,快排算法的优势就发挥不出来了,变成了最差者;选择排序依然优于冒泡排序,大约节省25%的时间。
三、在数组为反序(从大到小排列)的情况下
if __name__ == '__main__':
import time
print([i for i in range(50, 0, -1)])
t = time.time()
for i in range(10000):
array = [i for i in range(50, 0, -1)]
t0 = time.time() - t
print('生成10000次数据所需时间:', t0, 's')
t = time.time()
for i in range(10000):
array = [i for i in range(50, 0, -1)]
bubble_sort(array)
print('冒泡排序:', time.time() - t - t0, 's')
t = time.time()
for i in range(10000):
array = [i for i in range(50, 0, -1)]
select_sort(array)
print('选择排序:', time.time() - t - t0, 's')
t = time.time()
for i in range(10000):
array = [i for i in range(50, 0, -1)]
quick_sort(array)
print('快速排序:', time.time() - t - t0, 's')
测试结果:
生成10000次数据所需时间: 0.014925479888916016 s
冒泡排序: 2.075543165206909 s
选择排序: 0.7910571098327637 s
快速排序: 1.2525396347045898 s
生成10000次数据所需时间: 0.012000799179077148 s
冒泡排序: 2.0227086544036865 s
选择排序: 0.7382717132568359 s
快速排序: 1.2780859470367432 s
生成10000次数据所需时间: 0.012999534606933594 s
冒泡排序: 2.0591678619384766 s
选择排序: 0.7919540405273438 s
快速排序: 1.3123962879180908 s
总结:在反序(顺序正好是由大到小排列的)的情况下,快排依然不理想。冒泡排序也变得更差了,选择比冒泡节省大约60%的时间。选择排序是三者的最优算法。
“敲黑板”
1、虽然选择排序和冒泡排序的时间复杂度都是O(n^2),但时间复杂度和实际的时间消耗并不严格对等,在上述三种情况下,选择排序都优于冒泡排序。所以不要陷入“时间复杂度相同,其时间消耗就应该很相近”的误区中。
2、快排的优势只能在无序程度较高的情况下才能发挥出来,对于已经有序的数列(无论是正序还是反序),其表现都不会很优秀。
3、选择排序是三者中,选择排序是时间性能最稳定的一个,基本在0.6~0.8s;冒泡排序是三种中时间性能最不稳定的一个,基本在0.8~2.0s。
Mr.bai