解惑:迭代与递归

转载 2013年12月06日 11:43:11

(一)迭代法

迭代法也称辗转法,是一种不断用变量的旧值递推新值的过程。迭代算法利用计算机运算速度快、适合做重复性操作的特点,让计算机对一组指令(或一定步骤)进行重复执行,在每次执行这组指令(或这些步骤)时,都从变量的原值推出它的一个新值,是用计算机解决问题的一种基本方法。

迭代常用循环实现。

例1:分析下面的程序的功能

  1. int main(void)  
  2. {  
  3.           int x;  
  4.           cin>>x;  
  5.           while(x>0)  
  6.           {  
  7.                    cout<<x%10;  
  8.                    x=x/10;  
  9.        }  
  10.           cout<<endl;  
  11. }  

通过走查不难发现,输出的是x的倒序数。例如输入的x值为358,输出853。

在循环中,每一次迭代,x的数值都变小,直至为0结束循环,而在迭代中,每次都取出当前的最后一位数输出,于是x中的各位数,越靠后的越先输出,最终输出的是x的倒序数。

思考:如果将例子中的10换成2、8或16呢?

输出的结果自然是x对应的2、8或16进制数的倒序数。

联想到十进制数转换为其他进制数的方法。以转换为2进制数为例,方法为除2取余法,且最后得到的余数应在前面。我们将前面的迭代过程稍做修改,引入数组暂存余数解决此问题。

参考程序如下:

  1. int main(void)  
  2. {  
  3.           int x, n=0, a[50];  
  4.           cin>>x;  
  5.           while(x>0)  
  6.           {  
  7.                    a[n]=x%2;  
  8.                    x=x/2;  
  9.                    n++;  
  10.        }  
  11.           for(int i=n-1;i>=0; i--)  
  12.                    cout<<a[i];  
  13.           cout<<endl;  
  14. }  

还有一种迭代法叫近似迭代法,常用于数值计算中,如弦截法求解方程(p106例4.9)。例子中)重复步骤(2)和(3),直到|f(x)|<ξ(ξ为一个很小的正数)为止, 此时认为 f(x)≈0,获得了f(x)=0的近似解x。这个过程就是迭代。

请阅读下面的函数,其中f(x)是任意的方程,且调用时,要保证f(x1)和f(x2)异号。

  1. double root(double x1, double x2)     
  2. {  
  3.           double x,y,y1;  
  4.           y1=f(x1);  
  5.           do  
  6.           {  
  7.                    x=xpoint(x1,x2);   
  8.                    y=f(x);                       
  9.                    if(y*y1>0)  
  10.                    {        y1=y;  
  11.                             x1=x;  
  12.                    }  
  13.                    else  
  14.                             x2=x;  
  15.           }while(fabs(y)>=0.00001);  
  16.           return x;  
  17. }  


总结:利用迭代算法解决问题,需要做好以下三个方面的工作[1]:

1、确定迭代变量。在可以用迭代算法解决的问题中,至少存在一个直接或间接地不断由旧值递推出新值的变量,这个变量就是迭代变量。

2、建立迭代关系式。所谓迭代关系式,指如何从变量的前一个值推出其下一个值的公式(或关系)。迭代关系式的建立是解决迭代问题的关键,通常可以使用递推或倒推的方法来完成。

3、对迭代过程进行控制。在什么时候结束迭代过程?这是编写迭代程序必须考虑的问题。不能让迭代过程无休止地重复执行下去。迭代过程的控制通常可分为两种情况:一种是所需的迭代次数是个确定的值,可以计算出来;另一种是所需的迭代次数无法确定。对于前一种情况,可以构建一个固定次数的循环来实现对迭代过程的控制;对于后一种情况,需要进一步分析出用来结束迭代过程的条件。

 

(二)递归法

递归是计算机科学中的一种重要方法。

能采用递归描述的算法通常有这样的特征:为求解规模为N的问题,设法将它分解成规模较小的问题,然后从这些小问题的解方便地构造出大问题的解,并且这些规模较小的问题也能采用同样的分解和综合方法,分解成规模更小的问题,并从这些更小问题的解构造出规模较大问题的解。特别地,当规模N=1时,能直接得解。

例如求n!,由n!=n*(n-1)!,且1!=1,容易写出下面的函数:

  1. long fact(int n)  
  2. {  
  3.          long f;  
  4.        if (n==1)  
  5.                    f=1;  
  6.        else  
  7.                    f=n*fact(n-1);                   
  8.        return f;                            
  9. }  

递归函数在执行过程中,有一个递推的过程,求fact(n)先求fact(n-1),求fact(n-1)先求fact(n-2),……。在求得fact(1)=1后,再回归回去,求出fact(2)、fact(3)……直到得出fact(n)。递归,由递推和回归两个阶段组成。

递归不仅可以用于计算此类形式的问题。实际上,所有用迭代可以完成的任务用递归也可以完成,所有用递归完成的任务也可以用迭代完成。一般而言,递归更容易表达(人的效率),而迭代的执行效率更高(机器的效率)。递归程序的执行效率低是由于每一次敲击用函数都需要在计算机内保存相关的运行环境,既费时间又占空间,尤其是有些递归需要执行很多“层次”。所以在实践中,常用递归将问题分析清楚了,写出迭代程序来求解。

用递归的思路求解问题,需要找出这种递推和回归的过程来。

对比例1,我们给出相同功能的递归实现。

  1. int main(void)  
  2. {  
  3.          int x, n;  
  4.          cin>>x;  
  5.      f(x);  
  6.          cout<<endl;  
  7.          return 0;  
  8. }  
  9. void f(int a)  
  10. {  
  11.          if (a==0)  
  12.                    return;  
  13.          else  
  14.        {  
  15.                    cout<<a%10;          //(1)  
  16.                        f(a/10);              //(2)  
  17.        }  
  18. }  

请自行分析,输入x的值为358,输出将是?

试图实现十进制向二进制的转换,要保证对2取余数后,按照倒序取出来,需要将(1)、(2)两句换一下位置。即:

  1. void f(int a)  
  2. {  
  3.          if (a==0)  
  4.                    return;  
  5.          else  
  6.        {  
  7.                    f(a/2);                //(2)  
  8.                    cout<<a%2;  //(1)  
  9.        }  
  10. }  

为什么?走查一遍就清楚了。

最后总结,递归的基本概念和特点[1]:

程序调用自身的编程技巧称为递归( recursion)。

一个过程或函数在其定义或说明中又直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。用递归思想写出的程序往往十分简洁易懂。

一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。

注意:

(1) 递归就是在过程或函数里调用自身;

(2) 在使用递增归策略时,必须有一个明确的递归结束条件,称为递归出口。


原文地址:http://blog.csdn.net/sxhelijian/article/details/7100443



相关文章推荐

C++11:变长模板的迭代与递归扩展

迭代的运行效率始终强于递归,递归始终比迭代方便开发。 变长模板属于C++11中比较复杂的技术,在此简单介绍下。 #include using namespace std; template int...

java实现二分查找(迭代与递归)

二分查找是比较常用也是很高效的一种查找算法,其要求查找数据集的有序,采用顺序存储。在这里使用数组来简单的模拟数据集,并且要求数组升序元素排列,仅仅作为示例使用。如有错误欢迎批评指正。 public ...

【数据结构与算法学习笔记】PART1:算法分析(计算,计算模型,大O记号,算法分析,迭代与递归,动态控制)

在本科的时候就学过数据结构,那时候用的是清华大学C++版本的教材。上研究生之后,在实际学习与工程中愈发发觉数据结构的重要性,所以重新进行了数据结构的再学习,采用了清华大学邓俊辉副教授的视频课程,同时在...
  • abcSunl
  • abcSunl
  • 2016年08月03日 09:46
  • 409

C++11:变长模板的迭代与递归扩展

转自: http://blog.csdn.net/fawdlstty/article/details/49464097 迭代的运行效率始终强于递归,递归始终比迭代方便开发。 ...

树的遍历实现,前序遍历,中序遍历,后序遍历以及层次遍历的迭代与递归实现

用C++实现了树的前序遍历,中序遍历,后序遍历以及层次遍历。分别用迭代与递归进行实现。(能够直接运行)代码如下: //======================================...

Java 迭代与递归

因为最近公司项目需求,实现Java桌面程序实现树形结构 笔者查阅了大量的实现java树形的方法,其中就用到了递归,下面就简单说一下递归与迭代的区别和实现方式...

迭代与递归:To Iterate,Human; to Recurse, Divine.

引言 从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是什么呢?「从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是什么呢?『从前有座山,山里有座庙,...
  • edonlii
  • edonlii
  • 2014年06月04日 19:41
  • 1345

迭代与递归(及异同点的简单分析)以及Fibonacci数列的两种实现

迭代 迭代算法是用计算机解决问题的一种基本方法。它利用计算机运算速度快、适合做重复性操作的特点,让计算机对一组指令(或一定步骤)进行重复执行,在每次执行这组指令(或这些步骤)时,都从变量的原值推出它的...

递归、迭代与动态规划

在这篇博客里,我将以计算斐波那契数列指定位置的数为例介绍递归、迭代与动态规划。首先我们得弄清楚这三者的定义。 递归——程序调用自身,也就是函数自己调用自己。递归通常从顶部将问题分解,通过解决掉所有分...
  • wopelo
  • wopelo
  • 2017年07月09日 20:35
  • 148

迭代与递归的区别

 递归的基本概念:程序调用自身的编程技巧称为递归,是函数自己调用自己. 一个函数在其定义中直接或间接调用自身的一种方法,它通常把一个大型的复杂的问题转化为一个与原问题相似的规模较小的问题来解决...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:解惑:迭代与递归
举报原因:
原因补充:

(最多只允许输入30个字)