C++ 递归函数 详细解析——C++日常学习随笔

1. 递归函数

1.1 递归函数的定义

  • 递归函数:即在函数体中出现调用自身的函数,即函数Func(Type a,......)直接或间接调用函数本身;

  • 递归函数:在数学上,关于递归函数的定义如下:对于某一函数f(x),其定义域是集合A,那么若对于A集合中的某一个值x0,其函数值f(x0)由f(f(x0))决定,那么就称f(x)为递归函数;

  • 递归函数:不能定义为内联函数;

1.2 递归的本质

递归函数的例子:

(1)例子一:等差数列

数列1 3 5 7 9......代码实现输入一个数n,输出数列第n项的值。

cpp 复制代码
#include<iostream>
using namespace std;
int f(int n)
{
    if(n==1)
        return 1;
    else
        return f(n-1)+2;
}
int main()
{
    int n;
    cin >> n;
    cout << f(n);
    return 0;
}

解释:递归关系:f(n-1)+2,递归出口:1;

(2)例子二:阶乘n!

cpp 复制代码
递归的数学函数描述:
f(n)=1 (n=1)
f(n)=n*f(n-1) (n>1)
cpp 复制代码
递归的C++函数描述:
int f(nt n)
{
    if(n==1) 
        return 1;
    return n*f(n-1);
}

注:由于f(13)>2^32。所以对于int型(无符号类型)的表示范围,其n的取值范围只有1<=n<=12了。

(3)例子3:Fibonacci数列

斐波那契数列:1,1,2,3,5,8,13,21,34,55,89...

cpp 复制代码
递归的数学函数描述:
f(n)=0 (n=0)
f(n)=1 (n=1)
f(n)=f(n-1)+f(n-2) (n>2)
cpp 复制代码
递归的C++函数描述:
int f(int n)
{
    if((n==0) || (n==1))
        return n;
    return f(n-1)+f(n-2) ;
}
cpp 复制代码
#include<iostream>
using namespace std;
int f(int n)
{
    if(n==1||n==2)
        return 1;
    else
        return f(n-1)+f(n-2);
}
int main()
{
    int n;
    cin>>n;
    cout<<f(n);
    return 0;
}

(4)例子4:王小刀切饼:

王小二自夸刀工不错,有人放一张大的煎饼在砧板上,问他:"饼不许离开贴板,切n(1<=n<=100)刀最多能分成几块?

**输入格式:**输入切的刀数n

**输出格式:**输出切n刀最多切的块数

cpp 复制代码
#include<iostream>
using namespace std;
int f(int n)
{
    if(n==1)
        return 2;
    else
        return f(n-1)+n;
}
int main()
{
    int n;
    cin>>n;
    cout<<f(n);
    return 0;
}

解释:递归关系:f(n-1)+n,递归出口:n=1;

先列举几项就会发现规律

第一刀2

第二刀2+2=4

第三刀 4+3=7

第四刀 7+4=11

......

第n-1刀 i

第n刀 i+n

如图

(5)例子5:杨辉三角

cpp 复制代码
#include<iostream>
using namespace std;
int f(int x,int y)
{
    if(y==0||x==y)
        return 1;
    else
        return f(x-1,y-1)+f(x-1,y);
}
int main()
{
    int x,y;
    cin>>x>>y;
    cout<<f(x,y);
    return 0;
}

**(6)例子6:**最大公约数

cpp 复制代码
#include<iostream>
using namespace std;
int gcd(int a,int b)
{
    int r=a%b;
    if(r==0) return b;
    return gcd(b,r);
}
int main()
{
    int m,n;
    cin>>m>>n;
    cout<<gcd(m,n);
    return 0;
}

解释:

辗转相除法又名欧几里得算法,目的是求出两个正整数的最大公约数。它是最古老的算法,其可追溯刀公元前300年前。

这条算法基于一个定理:两个正整数a和b(a>b),他们的最大公约数等于a除以b的余数c和较小数b之间的最大公约数。

  • 递归有直接递归和间接递归之分:
  1. 直接递归:直接调用函数本身;
  2. 间接递归:指函数体中没有直接调用自身函数,而是调用了另一个函数,在那个函数里,出现了调用本函数的语句。或者,在那个函数里,又调用了一个其他函数,反复出现调用其它函数,而最后有一个函数调用了本函数;
  3. 注:递归函数在运行中,其调用与被调用函数的指令代码是同一个函数副本,只不过各个不同运行中的调用点作为状态的一部分,在栈中被分别保护了起来。因此,是C++的函数机制决定了递归操作中的数据独立性,因而使递归调用成为可能。

1.3 递归条件

  • 递归不能无限制地调用下去,因为栈空间是有限的。所以递归函数是有条件地调用自身,该条件就是递归的停止条件;
  • 递归函数中必须有完成终极任务的语句序列(如:return 1;),以使函数有意义,递归调用,并非终极;
  • 递归函数当然有递归调用语句,递归调用应有参数,而且参数值应该是逐渐逼近停止条件;
  • 递归条件应先测试,后递归调用,无条件递推的逻辑错误,编译器是检查不出来的,要靠程序员自己把握;
  • 注:消去递归,即大多数递归函数都能用非递归函数来替代,一般用循环语句实现。

1.4 递归函数的优缺点

优点:

  • 简化程序设计,使程序易读;
  • 作为对特殊问题的一种处理方法,递归仍然占有一席之地;
  • 许多高难算法的简捷描述,往往采用递归,特别对于能较快逼近停止条件的、优化了的递归函数;
  • 递归在迅速退栈的技术处理上得到了异常机制的帮助;

缺点:

  • 递归会迅速递增系统开销;
  • 在时间上,执行函数的调用与返回的次数明显要大于非递归函数;
  • 在空间上,栈空间资源会遭到空前的劫掠,随着每递归一次,栈内存就会多占用一截;
相关推荐
BeyondESH29 分钟前
Linux线程同步—竞态条件和互斥锁(C语言)
linux·服务器·c++
豆浩宇38 分钟前
Halcon OCR检测 免训练版
c++·人工智能·opencv·算法·计算机视觉·ocr
WG_171 小时前
C++多态
开发语言·c++·面试
Charles Ray2 小时前
C++学习笔记 —— 内存分配 new
c++·笔记·学习
重生之我在20年代敲代码2 小时前
strncpy函数的使用和模拟实现
c语言·开发语言·c++·经验分享·笔记
迷迭所归处8 小时前
C++ —— 关于vector
开发语言·c++·算法
CV工程师小林8 小时前
【算法】BFS 系列之边权为 1 的最短路问题
数据结构·c++·算法·leetcode·宽度优先
white__ice9 小时前
2024.9.19
c++
天玑y9 小时前
算法设计与分析(背包问题
c++·经验分享·笔记·学习·算法·leetcode·蓝桥杯
姜太公钓鲸2339 小时前
c++ static(详解)
开发语言·c++