定义

直接或间接地调用自身的算法称为递归算法。用函数自身给出定义的函数称为递归函数

【例2.1】设计求n!(n为正整数)的递归算法。
可递归地定义为:
n!=1 n=1 (1)
n!=n*fun(n-1) n>1 (2)
其中:
n=1 时,n!=1为边界条件
n>1 时,n!=n(n-1)!为递归方程
边界条件与递归方程是递归函数的二个要素,递归函数只有具备了这两个要素,才能在有限次计算后得出结果。

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_算法

一般来说,能够用递归解决的问题应该满足以下二个条件:
1.需要解决的问题可以转化为一个或多个子问题来求解,而这些子问题的求解方法与原问题完全相同,只是在数量规模上不同。
2.必须有结束递归的条件来终止递归。

递归算法设计

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递归算法_02

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递归_03

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递推_04

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递归_05

算法设计如下:
void digits(int n)
{ if (n!=0)
{
digits(n/10);
cout<<n%10<<“ “;
}
}

全排列:
【例2.4】排列问题
设计一个递归算法生成n个元素{a1,a2,…,an}的全排列。
存放于数组 A 的 n 个元素,生成其排列的步骤:
1)第一个元素不动,生成后面 n–1 个元素的排列
2)第一、第二个元素互换,生成后面 n–1 个元素的排列
3)最后,第一个、第n个元素互换,生成后面n–1个元素的排列;
为生成后面 n–1 个元素的排列,继续采取下面的步骤:
1)第二个元素不动,生成后面 n–2 个元素的排列
2)第二、第三个元素互换,生成后面 n–2 个元素的排列
3)最后,第二个、第 n 个元素互换,生成后面 n–2 个元
素的排列;
当排列的前 n–2 个元素确定后,为生成后面2个元素的排列,
可以:
1)第 n–1 个元素不动,生成后面 1 个元素的排列, 此时n个元素已构成一个排列;
2)第n-1、第n个元素互换,生成后面1个元素的排列,此时,n个元素已构成一个排列;
令排列算法perm(A,k,n)表示生成数组后面k个元素的排列。有:
1)基础步:k=1,只有一个元素,已构成一个排列;
2)归纳步:对任意的k,1<k≤n,为完成 perm(A,k,n),
逐一对第n–k与第n–k∽n 元素进行互换,每互换一次,就执行一次 perm(A,k -1,n) 操作,产生一个排列。

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_算法_06


请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_算法_07

void perm(Type A[ ], int k, int n)
  {   int i;
      if (k==1)
         for (i=0;i<n;i++)	// 已构成一个排列,输出它 
           cout << A[ i ];
       else {
         for (i=n-k;i<n;i++) {	// 生成后续的一系列排列 
           swap(A[ i ],A[ n-k ]);
            perm(A,k-1,n)
           swap(A[ i ],A[ n-k ]);
               }                                  
    }                            
}

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递推_08

显然它们不同列,若同列则有:q[k]==j;

对角线有两条,若它们在任一条对角线上,则构成一个等边直角三角形,即|q[k]-j|==|i-k|。

(q[k]==j) || (abs(q[k]-j)==abs(i-k))

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递归算法_09

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递归算法_10

bool place(int i,int j)		//测试(i,j)位置能否摆放皇后
{   if (i==1) return true;		//第一个皇后总是可以放置
    int k=1;
    while (k<i)			//k=1~i-1是已放置了皇后的行
    {	if ((q[k]==j) || (abs(q[k]-j)==abs(i-k)))
	    return false;
	k++;
    }
    return true;
}
void queen(int i,int n)		//放置1~i的皇后
{   if (i>n) 
	dispasolution(n);		//所有皇后放置结束
    else
    {	for (int j=1;j<=n;j++)	//在第i行上试探每一个列j
	    if (place(i,j))		//在第i行上找到一个合适位置(i,j)
	    {	q[i]=j;
		queen(i+1,n);
	    }
    }
}

递归小结
优点:结构清晰,可读性强,而且容易用数学归纳法来证明算法的正确性,因此它为设计算法、调试程序带来很大方便。
缺点:递归算法的运行效率较低,无论是耗费的计算时间还是占用的存储空间都比非递归算法要多。

递归算法转化非递归算法

把递归算法转化为非递归算法有如下两种基本方法:
   (1)用递推来实现递归函数。
   (2)用模拟系统的运行过程,通过分析只保存必须保存的信息,从而用非递归算法替代递归算法。

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递归_11

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递归算法_12

二、 用栈消除递归过程
采用一个用户定义的栈来模拟系统的递归调用工作栈。该方法通用性强,但本质上还是递归,只不过人工做了本来由编译器做的事情,优化效果不明显。
通常使用栈保存中间结果,从而将递归算法转化为非递归算法的过程。
通过Cooper变换、反演变换能将一些递归转化为尾递归,从而迭代求出结果。

递推式的计算

递归算法的执行时间可以用形式(即递推式)来表示,递推式也称为递归方程。求递归方程常用的方法有:
1)递推
2)生成函数
3)特征方程

递推

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递推_13

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递推_14

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递归_15

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_算法_16

生成函数

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递推_17

特征方程

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递归_18


请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递归_19

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递归算法_20


请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_算法_21

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递推_22

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递归_23


请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_算法_24

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递归算法_25

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递归算法_26

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递归算法_27

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递归算法_28


请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_算法_29


请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递推_30


请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递归算法_31

现在还没有一种寻找特解的有效方法。一般是根据g(n)的形式来确定特解。
 假设g(n)是n的m次多项式,即g(n)=c0nm+…+cm-1n+cm
则特解f”(n)=A0nm+A1nm-1+…+Am-1n+Am。
 代入原递归方程求出A0、A1、…、Am。
再代入初始条件(f(i)=bi,0≤i<k)求出系数得到最终通解

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递归算法_32


请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递推_33


请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递推_34


请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递归_35


请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递归算法_36

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递归算法_37

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_算法_38

递归树

用递归树求解递归方程的基本过程是:

  (1)展开递归方程,构造对应的递归树。

  (2)把每一层的时间进行求和,从而得到算法时间复杂度的估计。

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递归算法_39


请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递推_40


显然在递归树中,第1层的问题规模为n,第2的层的问题规模为n/2,依此类推,当展开到第k+1层,其规模为n/2k=1,所以递归树的高度为log2n+1。

  第1层有1个结点,其时间为n2,第2层有2个结点,其时间为2(n/2)2=n2/2,依次类推,第k层有2k个结点,其时间为2(n/2k)2=n2/2k-1。

叶子结点的个数为n个,其时间为n。将递归树每一层的时间加起来,可得:

  T(n)=n2+n2/2+ … +n2/2k-1+ … +n=O(n2)。

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递归算法_41

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递归算法_42

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_算法_43

请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_递推_44


请设计一个递归算法fibonacci数列的第20项的值python 设计递归算法求解n_算法_45