【转】循环、迭代、遍历和递归

loop、iterate、traversal和recursion这几个词是计算机技术书中常常会出现的几个词汇。众所周知,这几个词分别翻译为:循环、迭代、遍历和递归。乍一看,这几个词好像都与重复(repeat)有关,但有的又好像不彻底是重复的意思。那么这几个词到底各是什么含义,有什么区别和联系呢?下面就试着解释一下。程序员

  • 循环(loop),指的是在知足条件的状况下,重复执行同一段代码。好比,while语句。
  • 迭代(iterate),指的是按照某种顺序逐个访问列表中的每一项。好比,for语句。
  • 遍历(traversal),指的是按照必定的规则访问树形结构中的每一个节点,并且每一个节点都只访问一次。
  • 递归(recursion),指的是一个函数不断调用自身的行为。好比,以编程方式输出著名的斐波纳契数列。

有了以上定义,这几个概念之间的区别其实就比较清楚了。至于它们之间的联系,严格来说,它们彷佛都属于算法的范畴。换句话说,它们只不过是解决问题的不一样手段和方式,而本质上则都是计算机编程中达成特定目标的途径。算法

迭代

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

利用迭代算法解决问题,须要作好如下三个方面的工做:数组

  1. 肯定迭代变量。在能够用迭代算法解决的问题中,至少存在一个直接或间接地不断由旧值递推出新值的变量,这个变量就是迭代变量。
  2. 创建迭代关系式。所谓迭代关系式,指如何从变量的前一个值推出其下一个值的公式(或关系)。迭代关系式的创建是解决迭代问题的关键,一般可使用递推或倒推的方法来完成。
  3. 对迭代过程进行控制。在何时结束迭代过程?这是编写迭代程序必须考虑的问题。不能让迭代过程无休止地重复执行下去。迭代过程的控制一般可分为两种状况:一种是所需的迭代次数是个肯定的值,能够计算出来;另外一种是所需的迭代次数没法肯定。对于前一种状况,能够构建一个固定次数的循环来实现对迭代过程的控制;对于后一种状况,须要进一步分析出用来结束迭代过程的条件。

能够用迭代的算法有很经典的问题,好比兔子产子问题:假定你有一雄一雌一对刚出生的兔子,它们在长到一个月大小时开始交配,在第二月结束时,雌兔子产下另外一对兔子,过了一个月后它们也开始繁殖,如此这般持续下去。每只雌兔在开始繁殖时每个月都产下一对兔子,假定没有兔子死亡,在一年后总共会有多少对兔子?函数

还有上楼梯的走法问题:有一段楼梯有10级台阶,规定每一步只能跨一级或两级,要登上第10级台阶有几种不一样的走法?oop

迭代与循环

先从字面上看:优化

  • 迭代:“迭”:轮流,轮番,替换,交替,更换。“代”:代替。因此迭代的意思是:变化的循环,这种变化就是轮番代替,轮流代替。
  • 循环:不变的重复。

我的认为迭代是循环的一种,循环体代码分为固定循环体,和变化的循环体。spa

固定循环举例:.net

for($i=0; $i < 8; $i++){
    echo 'Welcome to NowaMagic';
}

实现迭代翻译

$sum = 0;

for($i = 1; $i <= 1000; $i++ ){
    $sum = $sum + i;
}
 

上面的迭代是常见的递增式迭代。相似的还有递减式迭代,递乘式迭代。

迭代的好处:迭代减小了冗余代码,提升了代码的利用率和动态性。

循环、迭代与递归

1. 递归算法与迭代算法的设计思路区别在于:函数或算法是否具有收敛性,当且仅当一个算法存在预期的收敛效果时,采用递归算法才是可行的,不然,就不能使用递归算法。

固然,从理论上说,全部的递归函数均可以转换为迭代函数,反之亦然,然而代价一般都是比较高的。但从算法结构来讲,递归声明的结构并不总可以转换为迭代结构,缘由在于结构的引伸自己属于递归的概念,用迭代的方法在设计初期根本没法实现,这就像动多态的东西并不老是能够用静多态的方法实现同样。这也是为何在结构设计时,一般采用递归的方式而不是采用迭代的方式的缘由,一个极典型的例子相似于链表,使用递归定义及其简单,但对于内存定义(数组方式)其定义及调用处理说明就变得很晦涩,尤为是在遇到环链、图、网格等问题时,使用迭代方式从描述到实现上都变得很不现实。

2. 递归实际上是方便了程序员难为了机器。它只要获得数学公式就能很方便的写出程序。优势就是易理解,容易编程。但递归是用栈机制实现的,每深刻一层,都要占去一块栈数据区域,对嵌套层数深的一些算法,递归会力不从心,空间上会之内存崩溃而了结,并且递归也带来了大量的函数调用,这也有许多额外的时间开销。因此在深度大时,它的时空性就很差了。

循环其缺点就是不容易理解,编写复杂问题时困难。优势是效率高。运行时间只因循环次数增长而增长,没什么额外开销。空间上没有什么增长。

3. 局部变量占用的内存是一次性的,也就是O(1)的空间复杂度,而对于递归(不考虑尾递归优化的状况),每次函数调用都要压栈,那么空间复杂度是O(n),和递归次数呈线性关系。

4. 递归程序改用循环实现的话,通常都是要本身维护一个栈的,以便状态的回溯。若是某个递归程序改用循环的时候根本就不须要维护栈,那其实这个递归程序这样写只是意义明显一些,不必定要写成递归形式。但不少递归程序就是为了利用函数自身在系统栈上的auto变量记录状态,以便回溯。

原理上讲,全部递归都是能够消除的,代价就是可能本身要维护一个栈。并且我我的认为,不少状况下用递归仍是必要的,它每每能把复杂问题分解成更为简单的步骤,并且很能反映问题的本质。

递归其实就是利用系统堆栈,实现函数自身调用,或者是相互调用的过程。在通往边界的过程当中,都会把单步地址保存下来,知道等出边界,再按照先进后出的进行运算,这正如咱们装木桶同样,每一次都只能把东西方在最上面,而取得时候,先放进取的反而最后取出。递归的数据传送也相似。可是递归不能无限的进行下去,必须在必定条件下中止自身调用,所以它的边界值应是明确的。就向咱们装木桶同样,咱们不能老是无限制的往里装,必须在必定的时候把东西取出来。比较简单的递归过程是阶乘函数,你能够去看一下。可是递归的运算方法,每每决定了它的效率很低,由于数据要不断的进栈出栈。

转自:http://www.nowamagic.net/librarys/veda/detail/2324

相关文章
相关标签/搜索