递归作法与动态规划作法的分析和比较

本文内容python

1、简介算法

2、动态规划原理编程

3、递归原理ide

4、实验预期现象函数

5、Python批量生成文件测试

6、遇到的困难与解决办法优化

6.1测试数据运行时间ui

6.2批量生成文件spa

7、递归作法相关实验3d

7.1源代码

7.1.1递归作法求解斐波那契数列

7.1.2测试递归次数

7.2实验数据

7.2.1测试运行时间

7.2.2测试递归次数

8、动态规划作法相关实验

8.1源代码

8.1.1动态规划作法求解斐波那契数列

8.2实验数据

8.2.2测试运行时间

9、实验结果比较

10、推测递归次数

10.1指数函数推测递归次数

10.2递推公式推测递归次数

10.3指数函数与递推公式求解递归次数对比

11、时间复杂度和空间复杂度分析

12、总结

1、简介:

  本篇博客以“斐波那契数列”为例,采用递归作法和动态规划作法对其求解,经过测量n1(1≤n1≤99,n1∈N)个数据运行时间以及测量递归作法n2(1≤n2≤41,n2∈N)个数据的递归次数,将获得的结果以柱状图的形式表现出来,进而对递作法和动态规划作法进行分析和比较。

  首先介绍斐波那契数列,斐波那契数列的排列是:1,1,2,3,5,8,13,21,34,55,89......。依次类推下去能够发现,它后一个数等于前面两个数的和。在这个数列中的数字,就被称为斐波那契数。由此能够得出“斐波那契数列”递推关系:

                                                                   F(n)=F(n-1)+F(n-2)(n∈N*)

2、动态规划原理

A* "1+1+1+1+1+1+1+1 =?" *

A: "上面等式的值是多少"

B : *计算"8!"

A*在上面等式的左边写上"1+" *

A: "此时等式的值为多少"

B : *quickly*"9!"

A : "你怎么这么快就知道答案了'' 

A: "只要在8的基础上加1就好了"

A: "因此你不用从新计算由于你记住了第一个等式的值为8!动态规划算法也能够说是'记住求过的解来节省时间''

由上面的对话能够知道动态规划算法的核心就是记住已经解决过的子问题的解。

动态规划算法是经过拆分问题,定义问题状态和状态之间的关系,使得问题可以以递推(或者说分治)的方式去解决。

能采用动态规划求解的问题的通常要具备3个性质:

1)最优化原理:若是问题的最优解所包含的子问题的解也是最优的,就称该问题具备最优子结构,即知足最优化原理。

2)无后效性:即某阶段状态一旦肯定,就不受这个状态之后决策的影响。也就是说,某状态之后的过程不会影响之前的状态,只与当前状态有关。

3)有重叠子问题:即子问题之间是不独立的,一个子问题在下一阶段决策中可能被屡次使用到。(该性质并非动态规划适用的必要条件,可是若是没有这条性质,动态规划算法同其余算法相比就不具有优点。

使用动态规划求解问题,最重要的就是肯定动态规划三要素:

1)问题的阶段。

2)每一个阶段的状态。

3)从前一个阶段转化到后一个阶段之间的递推关系。

3、递归原理

  先来分析一下递归算法的执行流程(以“斐波那契数列”为例),假如输入6,那么执行的递归树以下:

  

  上面的递归树中的每个子节点都会执行一次,不少重复的节点被执行,例如:fib(2)被重复执行了5次。因为调用每个函数的时候都要保留上下文,因此空间上开销也不小。这么多的子节点被重复执行,若是在执行的时候把执行过的子节点保存起来,后面要用到的时候直接查表调用的话能够节约大量的时间,这就是博客中提到的动态规划算法的优点。

4、实验预期现象

  动态规划算法的运行时间比较平稳,不随着测试数据的增大而改变。递归作法当测试数据越大时,运行时间越长,而且有不少重复计算的节点,因此预计递归算法的运行时间会呈指数增加。

5、python批量生成文件

  因为数据较多,为了简化工做、提升效率须采用批量执行的方法:

1.用记事本建一个空白的文件,后缀保存为.bat。此处以text.bat为例。

      

2.利用c语言进行编程,内容写好bat语句,并将输出结果重定向输入到步骤1存的text.bat文本中。

#include<stdio.h> main() { int i; for(i=1;i<=99;i++) { printf("ptime 文件名.exe<%d.txt>>文件名.txt\n",i); } }
View Code

3.重定向输出:将全部执行过程当中须要的文件放在同一目录下,在该目录下打开控制台,输入:要执行的文件名.exe>>文本名.bat(此处>>能够根据需求写成>,>>表示追加内容,>表示覆盖原有内容)

      

4.利用python写一段程序生成99个文本文件,每一个文本中存一个测试数据。

 i = 1
while (i < 100): s2 = 'C:/Users/Administrator/Desktop/a/' s = '.txt' s1 = s2+str(i) + s print(s1) f = open(s1, 'w') f.write(str(i)) f.close() i = i + 1
View Code

5.将全部执行过程当中须要的文件放入同一目录下,在该目录下打开控制台,执行1过程保存的text.bat文本。以上过程便可实现批量执行。

      

6、遇到的困难与解决办法

6.1测试数据运行时间

  解决办法:在每条执行语句前加ptime(ptime是测试运行时间的exe,精确到毫秒,在这个过程当中要求的时间精度比较高)。

6.2批量生成文件

  解决办法:利用python能够自动生成文本文件,代码如5-4。(生成的文件数量不一样,代码须要稍做修改)

7、递归方法相关实验

7.1源代码

7.1.1递归作法求解斐波那契数列

#include<stdio.h> 
int n = 0;//n表示输入的测试数据
int m = 0;//m表示调用函数后计算的结果
int fun(int p)
{
    
        if (p == 1 || p == 2)
         {
            return 1;
          }
     else
         {
            return fun(p - 1) + fun(p - 2);
          }
    
}
int main()
{
       scanf("%d", &n);
       m = fun(n);
       printf("%d",m);
       return 0;
}
View Code

7.1.2测试递归次数

#include<stdio.h> 
int n = 0;//n表示输入的测试数据
int m = 0;//m表示调用函数后计算的结果
int i=0;
int fun(int p,int t)
{
    
    if (p == 1 || p == 2)
    {
        i++;
        return 1;
    }
    else
    {
        i++;
        return fun(p - 1,t) + fun(p - 2,t);
    }
    
}
int main()
{
    scanf("%d", &n);
    m = fun(n,i);
    printf("%d\n", i);
    return 0;
}
View Code

7.2实验数据

7.2.1测试运行时间

    测试n(1≤n≤55,n∈N)个数据运行时间实验结果灰色列为测试数据,白色列为运行时间(单位S)。

      

                            图1 递归方法求解“斐波那契数列”测运行时间结果

      柱状图表示实验结果:

      

                   图2 递归方法求解“斐波那契数列”测运行时间结果柱状图

7.2.2测试递归次数

  测试n(1≤n≤41,n∈N)个数据递归次数实验结果。

      

                     图3 递归方法求解“斐波那契数列”测递归次数结果

      柱状图表示实验结果:

      

                    图4 递归方法求解“斐波那契数列”测递归次数结果柱状图

8、动态规划相关代码

8.1源代码

8.1.1动态规划作法求解斐波那契数列

#include<stdio.h>
int main() { int a[100]; int n; int i=2; a[0]=0; a[1]=1; a[2]=1; scanf("%d",&n); if(n==1) printf("1"); else{ while(1) { a[i]=a[i-1]+a[i-2]; if(i>=n) break; else i++; } printf("%d\n", a[i]); } return 0; }
View Code

8.2实验数据

8.2.2测试运行时间

    测试n(1≤n≤97,n∈N)个数据运行时间实验结果。

        

              图5 动态规划方法求解“斐波那契数列”测运行时间结果

        柱状图表示实验结果:

        

            图6 动态规划方法求解“斐波那契数列”测运行时间结果柱状图

9、实验结果比较

       

                     图7 递归方法求解每一个数据运行时间实验结果

        

                   图8 动态规划方法求解每一个数据运行时间实验结果

  经过两种方法运行时间的实验结果代表,递归作法的运行时间成指数增加,动态规划作法的运行时间不随测试数据的改变而变化。两种方法对比能够看出动态规划作法下降了时间复杂度,提升效率。实验结果与实验预期现象一致。

10、推测递归次数

  目的:当输入的测试数据较大时,运行时间较长,没法一一测试,因此须要推测测试结果。

10.1指数函数推测递归次数

  1. 经过图三测试不一样输入时递归的次数,能够推测出数据呈指数增加(与图四柱状图相同),设y=a^x(设x是测试数据,y是递归次数),代入图三数据求解得a=1.61。指数函数为:

                                                                                                   y=1.61^x

  2.写一段C程序批量执行利用指数函数对不一样的输入求解其递归次数。C代码:

#include<stdio.h> #include<math.h>
int main() { int x; float y; scanf("%d",&x); y=pow(1.61,x); printf("%f\n",y); return 0; }
View Code

  3.  执行结果:灰色列是测试数据n,白色列是求解出的递归次数

      

                       图9 指数函数推测递归次数实验结果

        折线图表示实验结果:

        

                        图10 指数函数推测递归次数实验结果折线图

    结论:经过这种方法,咱们测试数据较大时,能够推测递归须要的次数。

    缺点:与图三递归次数结果相比,能够看出指数函数求解获得的数据有偏差,不精确。

10.2递推公式推测递归次数

  1.根据递归方法求解“斐波那契数列”代码能够推导出求递归次数的递推公式:

                                f(p)=f(p-1)+f(p-2)+1

        设f(p)是递归次数。

  2.实验结果

    

                   图11 递推公式求解递归次数实验结果

    折线图表示实验结果:

    

                  图12 递推公式求解递归次数实验结果折线图

  结论:与图七相比能够得出,经过递推公式求解出的数据与实验测得的数据相同,由此能够证实经过递推公式推测递归次数偏差为零,能够更加精确的推测当输入的测试数据较大时须要递归的次数。

10.3指数函数与递推公式求解递归次数对比

    

                           图13 指数函数与递推公式求解递归次数对比图

  结论:经过对比图能够得出,两种方法的大体趋势相同,呈指数增加。不一样的是指数函数求解问题精度不高,有偏差。而递推公式求解此问题精确度高,偏差为零。

11、时间复杂度和空间复杂度分析

  算法复杂度分为时间复杂度和空间复杂度。其做用:时间复杂度是指执行算法所须要的计算工做量;而空间复杂度是指执行这个算法所须要的内存空间。(算法的复杂性体如今运行该算法时的计算机所需资源的多少上,计算机资源最重要的是时间和空间(即寄存器)资源,所以复杂度分为时间和空间复杂度。动态规划算法不随测试数据的增大而增大,因此动态规划算法的时间复杂度是O(1),空间复杂度是O(1)。

  如图所示,递归算法的时间复杂度为(二叉树的节点个数):O()=2^h-1=2^n(h为二叉树的高度),空间复杂度为树的高度:h即O(n)。

   

12、总结

  本篇博客以斐波那契数列为例,重点对动态规划算法和递归算法作分析比较,经过一系列的实验数据代表,动态规划算法与递归算法相比下降的时间复杂度和空间复杂度,从而提升工做效率,节省时间。本篇博客实验结果与预期实验结果一致。最后感谢老师指点,感谢高远博师兄耐心讲解相关知识,感谢代秋彤师姐每日批注,感谢李淼洋学长指出个人错误。感谢!

相关文章
相关标签/搜索