递归算法的解析

来源:互联网 发布:淘宝最好的店铺 编辑:程序博客网 时间:2024/05/21 00:50

递归算法

an = an-1 + 1;
你明白这个等式的意义吗?这个等式已经包含了递归算法的全部含义。an 表示 n个数的和,an-1 表示n-1个数的和 ,an = an-1 + 1;表示n个数的和可以通过n-1个数的和来求的。

上述说明哪些情况可以使用递归呢?
那就是:已知前一个步骤可以求得后一个步骤的结果的情况,并且前一个步骤和后一个步骤是有规律的。
比如汉诺塔问题:移n个盘是以移n-1个盘为条件的,两者的共同点是移盘。所以可以用f(n)表示移n个盘,f(n-1)表示移n-1个盘,那么移n个盘和移n-1个盘有什么关系呢?
这就需要预先分析问题才能得出具体的关系在这个问题中,把n个盘从a移到c需要三个步骤来完成。

  1. 上面n-1个盘从a移到b
  2. 最后第n个盘从a移到c
  3. n-1个盘从b移到c

已知n-1个盘从a移到b是可行的,为什么?
因为移1个盘是可行,那么移2个盘也是可行,移 3个盘是以移2个盘为条件的,所以移3个盘也是可行的,所以移n个 盘是可行的。
所以根据已知条件可以解得:

设f(n, a, b,c) 表示 把n个盘从a移到c 借助b 这里很关键,这是搞懂递归的关键关键。
那么把上面n-1个盘从a移到b 借助c 怎样表示呢?很明显是:f(n-1, a, c,b)

那么把第n个盘从a移到c怎样表示呢?很明显是:move(n,a,c)

那么把上面n-1个盘从b移到c 借助a 怎样表示呢?
很明显是:f(n-1, b, a,c)
所以f(n, a, b,c) = ( f(n-1, a,c,b) ,move(n,a,c), f(n-1, b,a,c))

这和等差等比数列一个原理。没有什么 特别的。问题有这样递推关系才可以使用这种方法。
如果要你计算1+2+8+22 的结果 你就不能使用递归。因为该问题的后一步骤与前一步骤不具有规律性,所以已知前一个步骤并不能求的后一个步骤的值
1+2+3+4 …这个问题就可以使用递归原因你懂了吧。至于爬楼梯问题,无限级分类 问题等一些递归问题,同理可以解决。

一句话:后一步骤依赖前一步骤并且二者联系具有规律性,运用递归必然成功。

递归算法的应用——汉诺塔的实现

#include<iostream>using namespace std;int numstep = 1;void move(int n, char from, char to) {    cout << numstep++ << " : " <<"move "<<n<<" from "<< from             << " to " << to << endl;}void hanoi(int n,char from, char depend, char to) {    if (n == 1) {        move(n, from, to);    }    else {        hanoi(n - 1, from, to, depend);        move(n, from, to);        hanoi(n - 1, depend, from, to);    }}int main() {    int a;    cin >> a;    char x = 'A', y = 'B', z = 'C';    hanoi(a, x, y, z);}

当修改一下汉诺塔的游戏规则:限制不能直接从起始的柱子直接到目的柱子而是一定要经过中间的柱子。

为了使用递归算法实现,就要分析后一步骤和前一步骤的联系。即要把N个盘子移动到目的柱子上怎么通过移上面N-1个盘子(这样就简化了问题)加一些移第N个盘子的步骤来实现。通过分析可以发现如下规律:

  1. 将1~N-1层盘子先全部从“左”移到“右”
  2. 将第N层盘子从“左”移到“中”
  3. 将第1~N-1层盘子全部从“右”移到“左”
  4. 将第N层盘子从“中”移到“右”
  5. 最后将1~N-1层盘子全部从“左”移到“右”
#include<iostream>using namespace std;int numstep = 1;void move(int n, char from, char to) {    cout << numstep++ << " : " <<"move "<<n<<" from "<< from << " to "         << to << endl;}void hanoi_reinforce(int n, char from, char depend, char to) {    if (n < 1)        return;    else {        hanoi_reinforce(n - 1, from, depend, to);        move(n, from, depend);        hanoi_reinforce(n - 1, to, depend, from);        move(n, depend, to);        hanoi_reinforce(n - 1, from, depend, to);    }}int main() {    int a;    cin >> a;    char x = 'A', y = 'B', z = 'C';    hanoi_reinforce(a, x, y, z);}

参考:《程序员代码面试指南》–左程云著
汉诺塔递归全过程

0 0