基础算法:递归

递归用处很广,可以将复杂问题简单化。

很多问题都可以使用递归算法或结合递归算法得到解决。

那么,设计递归算法的关键是什么?  其关键之处在于,正确分析出2种类型的节点:出口节点和入口节点

一    算法关键: 出口节点 , 入口节点

      递归问题可看做是由各个节点构成,而所有节点只能分为出口节点、入口节点两类。

       1)出口节点:   可直接计算此节点的值,不需借助其他节点

        那什么情况下,不必再递归了呢?

        确定结果了,自然就不用继续递归了,这也是递归的出口, 递归的根基。 所以这个根基必须判断好,这是递归是否成功的一个关键之处。

        因此,第一个的关键是:确定哪些节点是出口节点。

      

        2)入口节点: 无法直接计算此节点的值,但此节点的值可根据后续节点的值计算。

              入口节点与后续节点的数学或逻辑关系, 且如何用递归方式表示这个关系,则是递归算法的第二个关键。

         

二    什么问题可以用递归来处理?

      递归的过程,就是搜索的过程,搜索一个个的节点,找到出口节点。

      若问题满足下面条件,则可递归解决:

      A)  问题可看做为在很多节点中进行搜索

      B)  这些节点或者为出口节点 或者为入口节点

      C)  入口节点和后续节点间的关系 可用递归方式描述

      D)  出口节点在入口节点的后续路径中

下面举几个例子:

1  递增

第5个人的年龄比第4个的年龄大2岁,第4个人的年龄比第3个的年龄大2岁,第3个人的年龄比第2个的年龄大2岁,第2个人的年龄比第1个的年龄大2岁,第1个的年龄10岁.

[cpp] view plaincopy

  1. <strong>int age(int n)  
  2. {   
  3.     int c;  
  4.        
  5.     //是否为出口节点,若是,则不需继续递归  
  6.     if(n==1)  
  7.         c=10;  
  8.     else // 入口节点与后续节点的关系  
  9.         c=age(n-1)+2;  
  10.     return c;  
  11. }  
  12. </strong>  


 

2   阶乘

 5的阶乘是4的阶乘*5,4的阶乘是3的阶乘*4,3的阶乘是2的阶乘*3,2的阶乘是1的阶乘*2,1的阶乘是1的时候。

[cpp] view plaincopy

  1. int fac(int n)  
  2. {   
  3.     int c;  
  4.     if(n==1) c=1;  
  5.     else c=fac(n-1)*n;  // 将前n-1个看做一个处理单元  
  6.     return c;  
  7. }  


3  斐波那契数列

第一个和第二个数分别为1和1,从第三个数开始,每个数等于其前两个数之和(1,1,2,3,5,8,13…………)

[cpp] view plaincopy

  1. int rabbitNum(int n)  
  2. {  
  3.   
  4.     if (n==1||n==2) // 不需递归 找到出口  
  5.     {  
  6.         return n;  
  7.     }else{  
  8.                     
  9.         return rabbitNum(n-1)+rabbitNum(n-2);  
  10.   
  11.     }  
  12.   
  13. }  


4 汉诺塔

 

[cpp] view plaincopy

  1. void  Hannoi(int n,TCHAR a,TCHAR b,TCHAR c)  
  2. {  
  3.    
  4.     // 已经确定答案了,不需递归的情况  
  5.     if (n==1)  
  6.     {  
  7.         Move(1,a,c);  
  8.   
  9.     }else//需要继续递归的情况, 在这种情况下,关键是看:如何将问题划分为子问题处理单元,然后处理各个单元间的关系  
  10.   
  11.         // 本例:  将n个盘子 分成两个单元: 前n-1个盘子为一单元 、最后一个盘子为一单元  
  12.           
  13.         Hannoi(n-1,a,c,b);// 将第一个单元 从 a 移动到 b  
  14.         Move(n,a,c);      // 将第二个单元 从 a 移动到 c  
  15.         Hannoi(n-1,b,a,c);// 将第一个单元 从 b 移动到 c  
  16.     }  
  17.   
  18. }  

5  将输入的字符以相反顺序打印出来

[cpp] view plaincopy

  1. #include <stdio.h>   
  2. #include <string.h>   
  3.   
  4. void strv(TCHAR* p){   
  5.   
  6.     if(!*p)  // 不需继续递归  递归出口  
  7.         return;   
  8.     // 当p+1(包括p+1)之后的作为一个处理单元   
  9.     strv(p + 1);   
  10.     // 处理完毕 第一个单元后,输出本单元*p  
  11.     putchar(*p);   
  12. };   
  13.   
  14. int main(){   
  15.   
  16.     TCHAR* p = _T("ABCDEFGHIJK");   
  17.     strv(p);   
  18.     return 0;   
  19. };  

猜你喜欢

转载自blog.csdn.net/shenhua969/article/details/24985021