快速排序(续)

117 阅读2分钟

这里重申一下D&C的工作原理:

(1) 找出简单的基线条件;

(2) 确定如何缩小问题的规模,使其符合基线条件。

D&C并非可用于解决问题的算法,而是一种解决问题的思路。我们再来看一个例子。

给定一个数字数组。

1.png

你需要将这些数字相加,并返回结果。使用循环很容易完成这种任务。

def sum(arr):

total = 0

for x in arr:

total += x

return total

print sum([1, 2, 3, 4])

但如何使用递归函数来完成这种任务呢?

第一步:找出基线条件。最简单的数组什么样呢?请想想这个问题,再接着往下读。如果数

组不包含任何元素或只包含一个元素,计算总和将非常容易。

2.png

因此这就是基线条件。

第二步:每次递归调用都必须离空数组更近一步。如何缩小问题的规模呢?下面是一种办法。

3.png

这与下面的版本等效。

4.png

这两个版本的结果都为12,但在第二个版本中,给函数sum传递的数组更短。换言之,这缩小了问题的规模!

函数sum的工作原理类似于下面这样。

5.png

这个函数的运行过程如下。

6.png

别忘了,递归记录了状态。

7.png

提 示

编写涉及数组的递归函数时,基线条件通常是数组为空或只包含一个元素。陷入困境时, 请检查基线条件是不是这样的。

函数式编程一瞥

你可能想,既然使用循环可轻松地完成任务,为何还要使用递归方式呢?看看函数式编程 你就明白了!诸如Haskell等函数式编程语言没有循环,因此你只能使用递归来编写这样的函数。如果你对递归有深入的认识,函数式编程语言学习起来将更容易。例如,使用Haskell时,你可能这样编写函数sum。

8.png 注意,这就像是你有函数的两个定义。符合基线条件时运行第一个定义,符合递归条件时 运行第二个定义。也可以使用Haskell语言中的if语句来编写这个函数。 sum arr = if arr == []

then 0

else (head arr) + (sum (tail arr))

但前一个版本更容易理解。Haskell大量使用了递归,因此它提供了各种方便实现递归的语法。如果你喜欢递归或想学习一门新语言,可以研究一下Haskell。