【计算机算法与设计 C++版 】递归与分治策略

1.递归的概念

  • 递归算法
          直接或间接地调用自身的算法称为递归算法。

  • 递归函数
          用函数自身给出定义的函数称为递归函数。

  • 由分治法产生的子问题往往是原问题的较小模式,这就为使用递归技术提供了方便。在这种情况下,反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容易直接求出其解。这自然导致递归过程的产生。

  • 分治与递归像一对孪生兄弟,经常同时应用在算法设计之中,并由此产生许多高效算法。

①阶乘函数

在这里插入图片描述
递归算法:

int f1(int n)
    {
        if(n==0)
            return 1;
        return n*f1(n-1);
    }

消除递归:

在这里插入图片描述

int f2(int n)
{	int m=1;
	for(int i=1;i<=n;i++)
		m=m*i;
	return m;         }

②Fibonacci数列

在这里插入图片描述

递归算法:

int f1(int n)
{
	if(n<=1)
		return 1;
	return f1(n-1)+f1(n-2);
}

消除递归:

int f2(int n)
{	int m0=1,m1=1,m2;
	for(int i=2;i<=n;i++)
	{        m2=m0+m1;
		m0=m1;
		m1=m2;	}
	return m2;    
}

利用通项公式求𝑭(𝒏):

在这里插入图片描述

int f3(int n)
{	double x,y;
	x=0.5(sqrt(5.0)+1);
	y=pow(x,n+1)/sqrt(5.0);
	return y+0.5;
}

Ackerman函数——双递归函数

      当一个函数及它的一个变量由函数自身定义时,称这个函数为双递归函数。

      Ackerman函数𝑨(𝒏,𝒎)有两个独立的整型变量𝒎≥𝟎和𝒏≥𝟎,其定义如下:

在这里插入图片描述

𝑨(𝒏,𝒎)的自变量𝒎的每一个值都定义了一个单变量函数。
(1)当𝒎=𝟏时
∵𝑨(𝟏,𝟏)=𝑨(𝑨(𝟎,𝟏),𝟎)=𝑨(𝟏,𝟎)=𝟐
𝑨(𝒏,𝟏)=𝑨(𝑨(𝒏−𝟏,𝟏),𝟎)=𝑨(𝒏−𝟏,𝟏)+𝟐(n>1)
 ∴𝑨(𝒏,𝟏)=𝟐𝒏        (𝒏≥𝟏)
即𝑨(𝒏,𝟏)是函数乘2
(2)当𝒎=𝟐时
∵𝑨(𝒏,𝟐)=𝑨(𝑨(𝒏−𝟏,𝟐),𝟏)=𝟐𝑨(𝒏−𝟏,𝟐) (n>1)
𝑨(𝟏,𝟐)=𝑨(𝑨(𝟎,𝟐),𝟏)=𝑨(𝟏,𝟏)=𝟐
∴𝑨(𝒏,𝟐)=𝟐^𝒏
类似地可以推出,𝑨(𝒏,𝟑)=𝟐^(𝟐^(…^𝟐 ) ),其中2的层数是n
𝑨(𝒏,𝟒)的增长速度非常快,没有适当的数学式来表示。
递归过程和次数
int ct=0,a[65535][5]={0};
//用全局变量ct记递归调用次数
//a[n][m]记A1(n,m)被调用的次数
int A1(int n,int m)
{	a[n][m]++;	ct++;
	if(n==1&&m==0)		return 2;
	if(n==0)		return 1;
	if(m==0)		return n+2;
	return A1(A1(n-1,m),m-1);    }

运行问题:
1、溢出→𝒏,𝒎较大时
2、递归次数多


2.分治法的基本思想

基本思想
      将一个规模为𝒏的问题分解为𝒌个规模较小的子问题,这些子问题互相独立且与原问题相同。
      递归地解这些子问题,然后将各子问题的解合并得到原问题的解。
      以大整数的乘法为例,说明分治法。

//大整数乘法模拟实现
#include <iostream>
using namespace std;

int mul(int X,int Y,int n,int &ct) //ct记1位乘法次数。
{	
	int a,b,c,d,p,q,r,w,i;  
	if(n==1) 
	{
		cout<<endl<<"ct="<<ct++<<"   "<<X<<"*"<<Y<<"="<<X*Y;
		return X*Y;
	}
    w=10;
	for(i=1;i<n/2;i++) 
		w=10*w; //分拆为高位和低位两部分。
	a=X/w;b=X%w;c=Y/w;d=Y%w;
	cout<<endl<<"a="<<a<<"\nb="<<b<<"\nc="<<c<<"\nd="<<d<<endl;
	p=mul(a-b,d-c,n/2,ct);
	q=mul(a,c,n/2,ct);
	r=mul(b,d,n/2,ct);//分治及合成结果。
	
	//cout<<endl<<q*w*w+(p+q+r)*w+r<<endl;
	return (q*w*w+(p+q+r)*w+r);
}

int main()
{ 
	int x,y,n,ct=1;
	x=9118;y=3281;n=4;	
	mul(x,y,n,ct);
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值