算法子目录:https://blog.csdn.net/qq_41106844/article/details/105553931
快速排序流程图
代码:
from cat_time import cal_time
import random
def quick_sort(li,letf,right):
if letf<right: #确保列表长度大于等于2
mid = partition(li,letf,right)
# 对列表两边的元素继续快排
quick_sort(li,letf,mid-1)
quick_sort(li,mid+2,right)
def partition(li,left,right):
#选取 pivot 元素
tmp = li[left]
#大循环的条件是left 小于 right 用来控制一旦left和right重合,就结束排序
while left < right:
#右边的元素小于 tmp 元素 交换元素, 同时right-1
while left < right and li[right] >= tmp:
right -= 1
li[left] = li[right]
#同理
while left < right and li[left] <= tmp:
left += 1
li[right] = li[left]
#因为 left = right 所以返回谁都一样
return left
@cal_time
#递归算法要穿马甲来计时
def quick_sort_mj(li):
quick_sort(li,0,len(li)-1)
li = list(range(10000))
random.shuffle(li)
quick_sort_mj(li)
---------------
输出结果:
quick_sort_mj running time:0.033910512924194336 secs.
之前三个“low B”算法要算3秒,现在只需要0.03秒。
使用lambda的快排
import random
quick_sort = lambda array: array if len(array) <= 1 else quick_sort([
item for item in array[1:] if item <= array[0]
]) + [array[0]] + quick_sort([item for item in array[1:] if item > array[0]])
li = list(range(10000))
random.shuffle(li)
quick_sort(li)
匿名函数就是装一下用的,复杂度过高,还占用空间,速度比普通的三种排序快一点。
使用列表推导式的快排
from cat_time import cal_time
import random
def quick_sort2(li):
if len(li) <= 2:
return li
tmp = li[0]
left = [v for v in li[1:] if v <= tmp]
right = [v for v in li[1:] if v <= tmp]
left = quick_sort2(left)
right = quick_sort2(right)
return left + [tmp] +right
@cal_time
#递归算法要穿马甲来计时
def quick_sort_mj2(li):
quick_sort2(li)
li = list(range(10000))
random.shuffle(li)
quick_sort_mj2(li)
防超出递归深度,因为使用C的组件较多,速度比普通写法还要快一点(大约15%),但是空间复杂度变成了O(n)。
总结
稳定性:快排是一种不稳定排序,比如基准值的前后都存在与基准值相同的元素,那么相同值就会被放在一边,这样就打乱了之前的相对顺序
比较性:因为排序时元素之间需要比较,所以是比较排序
时间复杂度:快排的时间复杂度为O(nlogn),最坏情况是O(n2),直接造成栈溢出,Python停止运行。
解决方法是: pivot 从列表里随便选一个,然后和left交换。
空间复杂度:排序时需要另外申请空间,并且随着数列规模增大而增大,其复杂度为:O(nlogn)
归并排序与快排 :归并排序与快排两种排序思想都是分而治之。
但是它们分解和合并的策略不一样:归并是从中间直接将数列分成两个,而快排是比较后将小的放左边大的放右边,所以在合并的时候归并排序还是需要将两个数列重新再次排序,而快排则是直接合并不再需要排序,所以快排比归并排序更高效一些,可以从示意图中比较二者之间的区别。
快速排序有一个缺点就是对于小规模的数据集性能不是很好。