`

递归算法分析-分享

阅读更多
1. 深入认识递归

(1) 递归执行过程

   例子:求N!。
    这是一个简单的"累乘"问题,用递归算法也能解决。
    n! = n * (n - 1)!   n > 1
    0! = 1, 1! = 1      n = 0,1

    因此,递归算法如下:
   
fact(int n) {
	if(n == 0 || n == 1) 
	     return 1;
        else 
             return n * fact(n - 1);
    }

    以n=3为例,看运行过程如下:

    fact(3) ----- fact(2) ----- fact(1) ------ fact(2) -----fact(3)
    ------------------------------>  ------------------------------>
                递归                            回溯


  递归算法在运行中不断调用自身降低规模的过程,当规模降为1,即递归到fact(1)时,满足停止条件停止递归,开始回溯(返回调用算法)并计算,从fact(1)=1计算返回到fact(2);计算2*fact(1)=2返回到fact(3);计算3*fact(2)=6,结束递归。
   算法的起始模块也是终止模块。


(2) 递归实现机制

    每一次递归调用,都用一个特殊的数据结构"栈"记录当前算法的执行状态,特别地设置地址栈,用来记录当前算法的执行位置,以备回溯时正常返回。递归模块的形式参数是普通变量,每次递归调用得到的值都是不同的,他们也是由"栈"来存储。

(3) 递归调用的几种形式

    一般递归调用有以下几种形式(其中a1、a2、b1、b2、k1、k2为常数)。

   <1> 直接简单递归调用: f(n) {...a1 * f((n - k1) / b1); ...};
   
   <2> 直接复杂递归调用: f(n) {...a1 * f((n - k1) / b1); a2 * f((n - k2) / b2); ...};

    <3> 间接递归调用:  f(n) {...a1 * f((n - k1) / b1); ...},
                        g(n) {...a2 * f((n - k2) / b2); ...}。


2. 递归算法效率分析方法

   递归算法的分析方法比较多,最常用的便是迭代法。

  迭代法的基本步骤是先将递归算法简化为对应的递归方程,然后通过反复迭代,将递归方程的右端变换成一个级数,最后求级数的和,再估计和的渐进阶。
  <1> 例:n!
       算法的递归方程为: T(n) = T(n - 1) + O(1);
       迭代展开: T(n) = T(n - 1) + O(1)
                       = T(n - 2) + O(1) + O(1)
                       = T(n - 3) + O(1) + O(1) + O(1)
                       = ......
                       = O(1) + ... + O(1) + O(1) + O(1)
                       = n * O(1)
                       = O(n)

      这个例子的时间复杂性是线性的。

<2> 例:如下递归方程:
     
      T(n) = 2T(n/2) + 2, 且假设n=2的k次方。

      T(n) = 2T(n/2) + 2
           = 2(2T(n/2*2) + 2) + 2
           = 4T(n/2*2) + 4 + 2
           = 4(2T(n/2*2*2) + 2) + 4 + 2
           = 2*2*2T(n/2*2*2) + 8 + 4 + 2
           = ...
           = 2的(k-1)次方 * T(n/2的(i-1)次方) + $(i:1~(k-1))2的i次方
           = 2的(k-1)次方 + (2的k次方)  - 2
           = (3/2) * (2的k次方) - 2
           = (3/2) * n - 2
           = O(n)

      这个例子的时间复杂性也是线性的。


<3> 例:如下递归方程:
     
      T(n) = 2T(n/2) + O(n), 且假设n=2的k次方。

      T(n) = 2T(n/2) + O(n)
           = 2T(n/4) + 2O(n/2) + O(n)
           = ...
           = O(n) + O(n) + ... + O(n) + O(n) + O(n)
           = k * O(n)
           = O(k*n)
           = O(nlog2n) //以2为底
    
      一般地,当递归方程为T(n) = aT(n/c) + O(n), T(n)的解为:
      O(n)          (a<c && c>1)
      O(nlog2n)     (a=c && c>1) //以2为底
      O(nlogca)     (a>c && c>1) //n的(logca)次方,以c为底

   上面介绍的3种递归调用形式,比较常用的是第一种情况,第二种形式也有时出现,而第三种形式(间接递归调用)使用的较少,且算法分析
比较复杂。 下面举个第二种形式的递归调用例子。


  <4> 递归方程为:T(n) = T(n/3) + T(2n/3) + n

     为了更好的理解,先画出递归过程相应的递归树:
                            n                        --------> n
                    n/3            2n/3              --------> n
              n/9       2n/9   2n/9     4n/9         --------> n
           ......     ......  ......  .......        ......
                                                     --------
                                                     总共O(nlogn)


     累计递归树各层的非递归项的值,每一层和都等于n,从根到叶的最长路径是:
   
      n --> (2/3)n --> (4/9)n --> (12/27)n --> ... --> 1

     设最长路径为k,则应该有:
     
     (2/3)的k次方 * n = 1

     得到 k = log(2/3)n  // 以(2/3)为底

     于是 T(n) <= (K + 1) * n = n (log(2/3)n + 1)

     即 T(n) = O(nlogn)

    由此例子表明,对于第二种递归形式调用,借助于递归树,用迭代法进行算法分析是简单易行的。











分享到:
评论
5 楼 dk101 2010-07-14  
楼上“love_ai87 ”提到递归太深的话,容易导致JVM内存溢出,我也遇到过此问题,这个有什么好的解决办法吗?因为递归的深度(次数),大多数时候都是根据具体数据而定,所有就很头痛了。
4 楼 agao1985 2010-06-21  
哎 递归好难啊 怎么学都学不会 太笨了我
3 楼 love_ai87 2010-06-21  
递归次数太多的话,容易栈溢出
2 楼 maozj 2010-06-21  
ivaneve 写道
引用

  1. fact(int n) { 
   2.     if(n == 0 || n == 1)  
   3.          return 0; 
   4.         else  
   5.              return n * fact(n - 1); 
   6.     } 



return 0 ? 牛的。


仔细哦 已修正
1 楼 ivaneve 2010-06-21  
引用

  1. fact(int n) { 
   2.     if(n == 0 || n == 1)  
   3.          return 0; 
   4.         else  
   5.              return n * fact(n - 1); 
   6.     } 



return 0 ? 牛的。

相关推荐

    C++使用递归和非递归算法实现的二叉树叶子节点个数计算方法

    本文实例讲述了C++使用递归和非递归算法实现的二叉树叶子节点个数计算方法。分享给大家供大家参考,具体如下: /*求二叉树叶子节点个数 -- 采用递归和非递归方法 经调试可运行源码及分析如下: ***/ #include #...

    数据结构与算法分析C++描述习题答案

    ### 数据结构与算法分析C++描述习题答案 #### 一、引言 《数据结构与算法分析C++描述习题答案》这本书是基于Mark Allen Weiss教授的经典教材《数据结构与算法分析》编写的答案手册。Weiss教授的原著被誉为20世纪最...

    易语言二进制递归运算源码

    通过分析源码,我们可以学习到如何在易语言环境中实现复杂的计算逻辑,这对于提升易语言编程技巧和理解递归算法都有很大帮助。同时,这样的资源也可以作为一个学习案例,帮助初学者更好地掌握递归的概念和应用。

    零基础学算法--自己花钱买的资料

    1. **算法基础**:这部分主要介绍算法的基本概念,包括算法的定义、分类、设计原则以及分析方法。它会引导你理解算法在解决问题中的作用,如何评估算法的效率,以及常见的数据结构如数组、链表、栈、队列、树和图等...

    C++递归与分治法实现报告

    - 在递归算法中,时间复杂度的分析通常涉及到递归树的概念,通过分析递归树的深度和每一层的操作数量来确定整体复杂度。 - 对于二分查找,每次都将问题规模减半,因此时间复杂度为O(log n)。 - 幂运算的递归实现...

    java 算法入门到精通

    #### 四、数据结构与算法分析 - **核心数据结构**: - 数组、链表、栈、队列、哈希表等基本数据结构的实现与应用。 - 树形结构(二叉树、平衡树等)的特点与应用场景。 - 图的相关概念及其在实际问题中的应用。 -...

    二叉树非递归遍历程序

    在本篇文档中,作者分享了一个基于链表实现的二叉树非递归遍历算法,具体实现了前序遍历。这种遍历方法不使用递归调用,而是通过循环和辅助栈来完成遍历过程,有助于节省内存资源并提高执行效率。 ### 二叉树的基本...

    数据结构与算法分析(Java版)

    ### 数据结构与算法分析(Java版):关键知识点解析 #### 一、书籍概述 《数据结构与算法分析(Java版)》是一本由Robert Lafore编写的关于数据结构与算法的专业书籍。该书旨在通过Java语言的具体示例来帮助读者...

    算法参考资料Introduction-to-algorithms-3rd-edition

    由于提供的文件信息中,【标题】与【描述】并没有提供具体的内容细节,仅提供了文件的标题和描述,以及一个百度网盘分享...它不仅覆盖了算法理论,还包含了大量的实例分析和习题,帮助读者通过实践来加深对算法的理解。

    数据结构实验六.docx

    本实验的目的是让学生掌握递归算法设计和递归到非递归的转换方法,并了解单链表递归算法设计方法。 一、实验目的 通过本实验的学习,学生将领会基本递归算法设计和递归到非递归的转换方法,掌握单链表递归算法设计...

    数据结构算法与应用-C++语言描述

    递归算法是一种常见的编程技巧,它在解决一些特定问题时,比如汉诺塔问题、斐波那契数列计算等,可以发挥出色的作用。书中通过分析递归函数的执行过程和内存中的栈变化,阐释了递归过程中的递归调用和回溯机制。 ...

    武汉理工大学复试算法设计练习题(学长自己写的,其他要钱的都是盗版)

    4. **递归与分治--快速排序算法**:快速排序是C.A.R. Hoare提出的一种高效排序算法,采用分治策略,通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,然后分别对这两部分...

    C++基于递归和非递归算法求二叉树镜像的方法

    本文实例讲述了C++基于递归和非递归算法求二叉树镜像的方法。分享给大家供大家参考,具体如下: /*求二叉树镜像 -- 采用递归和非递归方法 经调试可运行源码及分析如下: ***/ #include #include #include using ...

    算法导论(第二版)完整答案 英文版

    - **渐进符号**:介绍大O符号、小o符号、Ω符号、ω符号以及Θ符号在算法分析中的应用。 ##### 知识点2:排序算法 - **堆排序**:讲解堆排序的基本原理,包括构建最大堆的过程以及如何通过调整堆来实现排序。 - **...

    js 递归json树实现根据子id查父id的方法分析

    分享给大家供大家参考,具体如下: 最近做了一个类似用js实现思维导图的功能,作为思维导图,一定会有树状结构的数据产生,在操作里面的节点时会经常需要查找节点 的父节点及父节点。 对于未知层级的树状数据,用for...

    数据结构与算法分析(Java版)

    6. 分治策略和递归:如何将大问题分解为小问题进行解决,以及递归算法的实现和效率分析。 7. 贪心算法:在每一步选择局部最优解来达到全局最优目标的方法。 8. 回溯法和分支限界法:用于求解组合优化问题的算法。 ...

    C++基于递归和非递归算法判定两个二叉树结构是否完全相同(结构和数据都相同)

    本文实例讲述了C++基于递归和非递归算法判定两个二叉树结构是否完全相同。分享给大家供大家参考,具体如下: /*两个二叉树结构是否相同(结构和数据都相同) -- 递归和非递归方法 经调试可运行源码及分析如下: ***/ ...

    卡尔曼滤波-基于Eigen3+Cpp11实现的卡尔曼滤波算法-附项目源码-优质项目分享.zip

    总结来说,"卡尔曼滤波-基于Eigen3+Cpp11实现的卡尔曼滤波算法-附项目源码-优质项目分享.zip"是一个涵盖了卡尔曼滤波理论与实践的资源包,结合了高效矩阵运算库Eigen3和现代化的C++11编程语言,为学习者提供了一个...

    数据结构与算法分析

    《数据结构与算法分析》是计算机科学中的一个基础领域,它研究的是如何在计算机中存储和组织数据,以及如何通过各种算法对这些数据进行有效处理。学习这门课程对于理解计算机软件的工作原理至关重要,它能够帮助...

Global site tag (gtag.js) - Google Analytics