可以使用递归或者栈来实现快排,以后的博客会记录使用栈的方式实现快排,本篇博客使用递归实现快排。递归的本质就是将一个大规模问题,转换成一个小规模问题,然后这些问题的处理方式都一样,最后通过函数自己调用自己的方式,逐层缩减问题的规模,最终解决问题。
现在来看快排的思路,假如要对4,3,6,7,5,2,9,8,1这个数列进行从小到大的排序,
第一步:先在数列中间位置取一个基准值,比如5(其实基准值的选取是任意的,我比较喜欢选中间的数作为基准值);
第二步:将所有小于5的数扔到5的左侧,所有大于等于5的数扔到5的右侧,所以经过第一次排序,就以5为基准,把数列分为了两个子数列:
4,3,2,1,5,9,7,6,8
我们在这一步不用考虑对这两个子数列进行排序,只要让左侧数列的数都小于5,右侧数列的数都大于等于5就好,这两个子数列都是乱序的也无所谓;
第三步:开始对这两个子数列——4,3,2,1和9,7,6,8进行相同的排序操作,这里以9,7,6,8为例,我们选取7为基准值,同样地,将所有小于7的数扔到7的左侧,所有大于等于7的数扔到7的右侧,所以把这个数列分为了两个部分:6,7,9,8。发现7右侧的数列 9,8 还是乱的,所以继续操作这个右数列,我们选9为基准值,将所有小于9的数扔到9的左侧,所有大于等于9的数扔到9的右侧,因此8小于9,所以8自然就被放到9的左侧,而没有数字比9大,所以9右侧的数列就是空的,9左侧的数列只有一个数字 8,9左右两侧的数列都无法再进行分割了,所以9,7,6,8这个数列就排好了顺序,变成了6,7,8,9。对于4,3,2,1这个数列,大家应该知道如何操作了吧?
通过上面三步操作,大家应该都发现规律了,首先这是一个典型的递归操作,但是有的同学可能会有这样的疑问,以基准值将数列分为两个部分,该如何保存这两部分的数据呢?答案是通过创建两个列表(数组),把小于基准值的数放在左列表中,把大于等于基准值的数放在右列表中,通过排序函数,不断在内部调用自己并传入左、右列表,最终再将排序结果拼在一起,就是最终的顺序了。同时格外强调递归的终止条件,注意看上面标粗画横线的部分,终止条件有两个——列表为空或列表只有一个数字,所以在代码中,当递归到列表为空或者列表中只有一个数字时,直接return传入的列表即可!
废话不多说上Python代码:
def quicksort(a): if len(a) == 0 or len(a) == 1: return a m = a[len(a) // 2] l = [] r = [] for i in range(0, len(a)): if i == len(a) // 2: continue if a[i] < m: l.append(a[i]) else: r.append(a[i]) return quicksort(l) + [m] + quicksort(r)