快速排序是一种很常用的排序算法,一般来说我们使用递归来实现它,从效率来说,快速排序不算快(时间复杂度O(n^2)),但是因为使用递归很好编写,容易理解,并且如果结合二分法的话可以把时间复杂度提到O(nlongn),这是一个还能接受的复杂度。
下面使用递归实现一个简单的sum函数,为下面的快速排序做为铺垫,递归的意思是在函数内部直接或者间接的调用自身。如下面的mysum函数,我通过不断调用本身,把列表中的元素pop出去,那么到最后一定会满足基线条件,最后回溯。然后调用我们解释器的调用栈,把每个mysum函数中记录num1值相加
list1 = []
list2 = [1, 7, 3, 4]
def mysum(list):
if not list:
return 0
if len(list) < 2: # 基线条件
return str(list[0])
num1 = list.pop(0)
return num1 + mysum(list)
print(mysum(list1))
print(mysum(list2))
调用栈,是值我们每次新调用一个函数,那么在内存中的调用栈就会新加一分数据,栈的思想是后进先出,所以后面调用的函数会先被拿出来。
快速排序:快速排序的复杂度是与选择的基线条件以及基准值的选择有很大的关系,比如同样适用快速排序,将数组的第一个数作为基准数的复杂度是O(n^2),而如果结合了二分法,把中间数作为基准数,复杂度可以优化到O(nlogn)。
使用第一个数作为基准数的快速排序
list1 = []
list2 = [1, 7, 3, 4, 9, 2]
def mysort(list):
if len(list) < 2:
return list
num1 = list[0]
less = [i for i in list[1:] if i <= num1]
big = [i for i in list[1:] if i > num1]
return mysort(less) + [num1] + mysort(big)
print(mysort(list2))
# 此遇到一个问题,return mysort(less) + [num1] + mysort(big)这行代码,因为我们需要返回一个,所以num1需要是列表,使用[num1]可以正常运行,list(num1)会报错
结合二分法实现快速排序
list1 = []
list2 = [1, 7, 3, 4, 9, 2]
def mysort(list):
if len(list) < 2:
return list
center = len(list)//2
num1 = list[center]
less = [i for i in list[0:] if i < num1]
big = [i for i in list[0:] if i > num1]
return mysort(less) + [num1] + mysort(big)
print(mysort(list2))