​ 今天突发奇想,能不能用更简洁的方式实现快排,说干就干。

​ 首先来讲讲一般的普通解法,以升序为例,选择一个基值(一般为第一个数),将其放在中间位置,定义两个游标,从左边寻找比基值大的,从右边找比基值小的,左右两个游标交换位置,继续执行此操作,直到两个指针相遇,一轮结束。然后开始下一轮操作,对基数左右两边的数继续执行上述操作,直到排序成功。

​ 上面是快排的最基本思路,利用递归可以轻易实现,那么可不可以再简易一些,更让人容易理解一些呢?

​ 简单分析一下可以发现,每轮操作的最终目的都是将比基值大的数放在基值右边,比基值小的放在基值左边,此时就可以换个思路,进行遍历操作,遇到比基值小的,与左游标交换,遇到比基值大的,与右游标交换,相等则跳过,以下是代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def quick_sort_1(sorting, left, right):
if right <= left: #判断左右游标是否相遇
return
a = i = left
b = right
pivot = sorting[left] #设第一个数为基值
while i <= b:
#如果遍历的值小于基值,与左游标交换
if sorting[i] < pivot:
sorting[a], sorting[i] = sorting[i], sorting[a]
a += 1
i += 1
#如果遍历的值大于基值,与右游标交换
elif sorting[i] > pivot:
sorting[b], sorting[i] = sorting[i], sorting[b]
b -= 1
#如果等于则跳过
else:
i += 1
#递归左边的数据
quick_sort_1(sorting, left, a - 1)
#递归右边的数据
quick_sort_1(sorting, b + 1, right)

​ 此代码更容易理解,让我们更近一步,再抽象一些,整个快排的操作都在做一件什么事?基值在中间,将大于基值的数放到右边,小于基值的数放到左边,不断地重复这样的操作。直接上代码:

1
2
3
4
5
6
7
def quick_sort_2(a):
if len(a) <= 1:
return a
q = a[0]
g = [e for e in a[1:] if e > q]
le = [e for e in a[1:] if e <= q]
return quick_sort_2(le) + [q] + quick_sort_2(g)