C++中的递归

参考博文:https://blog.csdn.net/u012936940/article/details/79672460#commentBox

1.概念
        递归函数即自调用函数,在函数内部直接的或者间接地调用自己。在求解某些具有随意性的复杂问题时经常使用递归,如要求编写一个函数,将输入的任意长度的字符串反向输出。普通做法是将字符串放入数组中然后将数组元素反向输出即可,然而这里的要求是输入是任意长度的,总不能开辟一个很大的空间保存字符串吧?这时候递归就起作用了。递归采用了分治的思想,将整体分割成部分,从最小的基本部分入手,逐一解决,其中部分通常和整体具有相同的结构,这样部分可以继续分割,直到最后分割成基本部分。

        递归函数必须定义一个终止条件,即什么情况下终止递归,终止继续调用自己,如果没有终止条件,那么函数将一直调用自己,知道程序栈耗尽,这时候等于是写了一个Bug!

总结递归的特点:

(1) 使用递归时,一定要有明确的终止条件!

(2) 递归算法解题通常代码比较简洁,但不是很容易读懂。

(3) 递归的调用需要建立大量的函数的副本,尤其是函数的参数,每一层递归调用时参数都是单独的占据内存空间,他们的地址是不同的,因此递归会消耗大量的时间和内存。而非递归函数虽然效率高,但相对比较难编程。

(4) 递归函数分为调用和回退阶段,递归的回退顺序是它调用顺序的逆序。

2.实践
斐波那契数列当n>3时,第n个元素的值等于第n-1个元素和n-2个元素的和,当n不确定具体数值时,可以通过递归的方式实现

int Fib(int n) {
    if (n < 2)
        return 1;
 
    return Fib(n - 1) + Fib(n - 2);
}
void test_fib(int n) {
    int fib1[n], fib2[n];
    fib1[0] = 1;
    fib1[1] = 1;
    fib2[0] = 1;
    fib2[1] = 1;
    for (int i = 2; i < n; i++) {
        fib1[i] = Fib(i);
        fib2[i] = fib2[i - 1] + fib2[i - 2];
    }
    cout << "use func Fib() " << endl;
    for (int i = 0; i < n; i++) {
        cout << fib1[i] << ' ';
    }
    cout << endl;
    cout << "use for loop " << endl;
    for (int i = 0; i < n; i++) {
        cout << fib2[i] << ' ';
    }
    cout << endl;
}
最终由递归得到的斐波那契数列和由for循环得到的数列相同。

阶乘问题同样可以通过递归实现,代码为

int Factorial(int n) {
    if (n == 1)
        return 1;
    return n * Factorial(n - 1);
}
当n=5时,函数的调用过程如下图所示

汉诺塔问题是指一共有3根针,其中两根为空,另外一根针从上到下按照尺寸穿好了若干个盘子,上面的小下面的大,要求是每次移动一个盘子,将所有的盘子移动到另一根针上,并且所有的针上的盘子都满足上小下大的要求,如下图

这个问题同样可以使用递归的方式解决,思路如下

因此发现以上步骤实际上是一个重复的过程,则整个问题可以使用递归解决,当盘子个数为1时直接移动即可,为n时则先借助一根针将n-1个盘子移动到另一根针上,而n-1根针可以先移动n-1-1根针,如此往复。代码如下

void move(int n, char x, char y, char z) {
    // 将n个盘子从x借助y移动到z上
    if (1 == n) {
        cout << x << "-->" << z << endl;
    } else {
        // 将n-1个盘子从x借助z移动到y上
        move(n - 1, x, z, y);
        // 将第n个盘子从x移动到z上
        cout << x << "-->" << z << endl;
        // 将n-1个盘子从y借助x移动到z上
        move(n - 1, y, x, z);
    }
}

--------------------- 
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
买书问题 dp实现 题目:买书 有一书店引进了一套书,共有3卷,每卷书定价是60元,书店为了搞促销,推出一个活动,活动如下: 如果单独购买其一卷,那么可以打9.5折。 如果同时购买两卷不同的,那么可以打9折。 如果同时购买三卷不同的,那么可以打8.5折。 如果小明希望购买第1卷x本,第2卷y本,第3卷z本,那么至少需要多少钱呢?(x、y、z为三个已知整数)。 1、过程为一次一次的购买,每一次购买也许只买一本(这有三种方案),或者买两本(这也有三种方案), 或者三本一起买(这有一种方案),最后直到买完所有需要的书。 2、最后一步我必然会在7种购买方案选择一种,因此我要在7种购买方案选择一个最佳情况。 3、子问题是,我选择了某个方案后,如何使得购买剩余的书能用最少的钱?并且这个选择不会使得剩余的书为负数 。母问题和子问题都是给定三卷书的购买量,求最少需要用的钱,所以有"子问题重叠",问题三个购买量设置为参数, 分别为i、j、k。 4、的确符合。 5、边界是一次购买就可以买完所有的书,处理方式请读者自己考虑。 6、每次选择最多有7种方案,并且不会同时实施其多种,因此方案的选择互不影响,所以有"子问题独立"。 7、我可以用minMoney[i][j][k]来保存购买第1卷i本,第2卷j本,第3卷k本时所需的最少金钱。 8、共有x * y * z个问题,每个问题面对7种选择,时间为:O( x * y * z * 7) = O( x * y* z )。 9、用函数MinMoney(i,j,k)来表示购买第1卷i本,第2卷j本,第3卷k本时所需的最少金钱,那么有: MinMoney(i,j,k)=min(s1,s2,s3,s4,s5,s6,s7),其s1,s2,s3,s4,s5,s6,s7分别为对应的7种方案使用的最少金钱: s1 = 60 * 0.95 + MinMoney(i-1,j,k) s2 = 60 * 0.95 + MinMoney(i,j-1,k) s3 = 60 * 0.95 + MinMoney(i,j,k-1) s4 = (60 + 60) * 0.9 + MinMoney(i-1,j-1,k) s5 = (60 + 60) * 0.9 + MinMoney(i-1,j,k-1) s6 = (60 + 60) * 0.9 + MinMoney(i-1,j,k-1) s7 = (60 + 60 + 60) * 0.85 + MinMoney(i-1,j-1,k-1)

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值