分而治之
快速排序需要使用 分而治之(Divide and conquer, D&C)策略来将一个序列风儿较小和较大的两个子序列,然后递归的排序两个子序列。
分而治之需要三个步骤:
- 找出基线条件,这个条件需要尽可能的简单
- 不断的将问题分解,直到符合基线条件
一个简单的例子,假设我们有一个数组:[1,2,3,4,5],而我们需要求得这个数组中的元素的和。
一个简单的方法是使用循环来进行求解:
def sum(arr):
total = 0
for x in arr:
total += x
return total
print (sum([1,2,3,4,5]))
求得结果为:
15
但是我们可以采用分而治之的思想来进行:
[1,2,3,4,5]=1+[2,3,4,5]=1+2+[3,4,5]=1+2+3+[4,5]=1+2+3+4+5[1,2,3,4,5]=1+[2,3,4,5]=1+2+[3,4,5]=1+2+3+[4,5]=1+2+3+4+5
极限条件为:如果数组不包含任何元素或者只包含一个元素,那么计算总和将会是一件非常简单的事情。
不断的将问题分解:每次调用递归都必须离空数组更进一步。
我们可以写出这样的一个函数:
def sum(list):
#如果是空数组,则直接返回0
if list == []:
return 0
#在这里进行了递归
#被传入的list为[2,3,4,5]
#接着是[3,4,5] 如此往复
return list[0] + sum(list[1:])
print (sum([1,2,3,4,5]))
运行的结果为:
15
虽然这两种方法都能够获得结果15,但是第二种方法给sum传递的数组的大小更小,也就是说缩小了问题的规模。
快速排序
首先我们需要考虑到数组为空或者只有一个元素的情况:
def quicksort(array):
if len(array) < 2:
return array
接着我们只需要选择一个基准值,然后进行递归:
#选定一个基准值
pivot = array[0]
#小于基准值的元素作为一个数组
less = [i for i in array[1:] if i <= pivot]
#大于基准值的元素作为一个数组
greater = [i for i in array[1:] if i > pivot]
#进行递归
return quicksort(less) + [pivot] + quicksort(greater)
便可以完成算法了:
def quicksort(array):
if len(array) < 2:
return array
else:
#选定一个基准值
pivot = array[0]
#小于基准值的元素作为一个数组
less = [i for i in array[1:] if i <= pivot]
#大于基准值的元素作为一个数组
greater = [i for i in array[1:] if i > pivot]
#进行递归
return quicksort(less) + [pivot] + quicksort(greater)
我们可以进行测试:
print (quicksort([30,10,20,40,50]))
得到的结果为:
[10, 20, 30, 40, 50]
过程可以展示如下:
以array[0]作为一个基准点可以得到[10,20][30][40,50]的三个数组以array[0]作为一个基准点可以得到[10,20][30][40,50]的三个数组
同理将[10,20]传递到算法中可以得到[][10][20]三个数组同理将[10,20]传递到算法中可以得到[][10][20]三个数组
同理可以得到[][40][50]三个数组同理可以得到[][40][50]三个数组
最终得到[10,20,30,40,50]