ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

六、递归

2022-09-10 12:01:19  阅读:189  来源: 互联网

标签:输出 return 递归 PanDaoxi Author int


从今天开始,我们就要初涉算法,请大家做好心理准备嗷!

递归

递归这个名词大家估计都耳熟能详吧,那咱们跳过吧 但是我们还是要好好学习递归的,因为递归对于我们后面学习深搜、二叉树是非常重要的。

如果你还没听说过递归,那么我告诉你,你可以把递归理解成一种特殊的循环。还记得小时候听过的“老和尚讲故事”吗?讲来讲去,你就陷入了循环,自己讲起了我自己。

// Author:PanDaoxi
#include <bits/stdc++.h>
using namespace std;
void story(){
    cout << "从前有座山,山上有座庙。庙里有个老和尚给小和尚讲故事,讲的是什么呢?" << endl;
    story(); // 我自己执行我自己
}
int main(){
    story();
    return 0;
}

然后你会发现,控制台上输出了非常多的故事,直到你把它关掉,这就类似于死循环,我们称这种递归叫做无穷递归
前段时间我们说 \(while\) 循环的时候,那个括号里的表达式就是循环条件。如果不满足循环条件,才会继续运行后面的指令。所以我们想让递归结束,必须要设置边界条件,这样就能实现有穷递归
比如说,我们刚才讲故事的例子,如果我们想让程序输出 \(10\) 遍,那么该怎么写?

// Author:PanDaoxi
#include <bits/stdc++.h>
using namespace std;
void story(int k){ // k 表示故事讲了k遍
    if(k > 10){ // 讲了10遍以上
        printf("故事讲完啦");
        return; // 退出递归
    }
    printf("第%d遍:从前有座山,山上有座庙。庙里有个老和尚给小和尚讲故事,讲的是什么呢?\n", k);
    story(k+1); // 讲了一遍故事
}
int main(){
    story(1); // 从第一遍开始讲故事
    return 0;
}

image

当然你也可以自由地控制递归次数,要多上机尝试、练习。
我们来做个题儿应用一下吧:

在这里插入图片描述
这个题其实用循环也能过,官方给的标签也是循环结构,但是我喜欢用递归解。
程序也并不难,如下:
在这里插入图片描述

回溯

可能有的小伙伴一听“回溯”,就吓得不轻:难道你要给我讲深搜?
其实递归的回溯并不难好叭,大家模拟一下就可以咯。

请你阅读以下这个程序,告诉我,结果会输出多少?

// Author:PanDaoxi
#include <bits/stdc++.h>
using namespace std;
void f(int k){
    if(k > 5) return;
    printf("%d ", k);
    f(k+1);
    printf("%d ", k);
}
int main(){
    f(1);
    return 0;
}

答案是:

1 2 3 4 5 5 4 3 2 1

为什么会这样?我们来模拟一下。

最开始,主函数调用给进函数的参数 \(k=1\)。进来以后走流程:

  1. 判断:\(k\) 如果大于 \(5\) 就退出。
  2. 输出当前 \(k\) 的值;
  3. 递归 \(k\) 增加 \(1\)。
  4. 递归到边界时,输出 \(k\) 的值。

可见如果递归到 \(k=5\) 时程序先输出,后面程序尝试递归 \(k=6\) 发现:诶,\(k>5\) 了,该退出递归了!
退出了递归 \(k=6\),程序继续执行当前层数(\(k=5\))的后面的命令,输出了 \(5\),然后 \(k=5\) 的递归结束,继续进行 \(k=4\) 的递归……
长此以往, 运行到 \(k=1\) 时(又回到了主程序给定的 \(k\) 的值时),递归结束。

利用这个特点,我给你出一道题吧。

【角谷猜想的过程】
现在,给你一个数,要求你把角谷猜想(就是上面那个)的过程展现出来。
例如:

  • 输入 \(1\),应该输出:1
  • 输入 \(5\),应该输出:((1)*2)*2+1
  • 输入 \(123\),应该输出:((((((1)*2+1)*2+1)*2+1)*2)*2+1)*2+1
  • 输入\(114514\),应该输出:((((((((((((((((1)*2+1)*2)*2+1)*2+1)*2+1)*2+1)*2+1)*2+1)*2)*2+1)*2)*2+1)*2)*2)*2+1)*2
  • 输入 \(1919180\),应该输出:((((((((((((((((((((1)*2+1)*2+1)*2)*2+1)*2)*2+1)*2)*2)*2+1)*2)*2)*2)*2+1)*2+1)*2)*2)*2+1)*2+1)*2)*2

不信你可以把它还原回去,还是原来那个数。
在这里插入图片描述

这个程序,我们可以这么写:

// Author:PanDaoxi
#include <bits/stdc++.h>
using namespace std;
void f(int k){
    if(k == 1){
        cout << 1;
        return;
    }
    cout << "(";
    bool flag = k&1;
    f(flag ? ((k-1)/2) : (k/2));
    cout << ")*2";
    if(flag) cout << "+1";
}
int main(){
    int n;
    cin >> n;
    f(n);
    return 0;
}

做俩简单的题儿:
在这里插入图片描述

// Author:PanDaoxi
#include <bits/stdc++.h>
using namespace std;
double f(double x, int n){
    if(n == 1) return sqrt(1.0 + x);
    return sqrt(n + f(x, --n));
}
int main(){
    double x;
    int n;
    cin >> x >> n;
    cout << fixed << setprecision(2) << f(x, n);
    return 0;
}

在这里插入图片描述

// Author:PanDaoxi
#include <bits/stdc++.h>
using namespace std;
double f(double x, int n){
    if(n == 1) return x / (1.0+x);
    return x / (n + f(x, --n));
}
int main(){
    double x;
    int n;
    cin >> x >> n;
    cout << fixed << setprecision(2) << f(x, n);
    return 0;
}

好啦好啦,后面我们就要趁热打铁学深搜了!
我目前的规划是:

  • 递归
  • 深搜
  • 排序
  • 贪心
  • 递推
  • 栈和队列
  • 二分
  • 广搜
  • 动态规划
  • …………

标签:输出,return,递归,PanDaoxi,Author,int
来源: https://www.cnblogs.com/PanDaoxi/p/16676181.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有