看了很多博主的博文,加上看了几个视频,做了一些题目,感觉对递归有了一些认识,希望大家观看以后会对自己有所帮助。

递归的算法详解

  • 递归的定义

如果一个对象部分地由它自身组成或按它自己定义,则称它是递归的,所以说递归就是函数/过程/子过程在运行过程中直接或间接调用自身而产生的重入现象。

  • 递归算法包含的两个部分

1 由其自身定义的与原始问题类似的更小规模的子问题(只有数据规模不同),它使递归过程持续进行,称为一般条件。
2 所描述问题的最简单的情况,它是一个能控制递归过程结束的条件,称为基本条件。(递归出口)

  • 递归的基本思想

就是把一个规模大的问题分为若干个规模较小的子问题求解,而每一个子问题又可以分为几个规模更小的子问题。
基本上,所有的递归问题都可以用递推公式来表示。
最重要的一点就是假设子问题已经解决了,现在要基于已经解决的子问题来解决当前问题;
或者说,必须先解决子问题,再基于子问题来解决当前问题
或者可以这么理解:递归解决的是有依赖顺序关系的多个问题。

  • 递归的优缺点

优点
逻辑清楚,结构清晰,可读性好,代码简洁,效率高(拓展:DFS深度优先搜素,前中后序二叉树遍历)
缺点
函数调用开销大,空间复杂度高,有堆栈溢出的风险。

  • 什么样的问题可以用递归来求解?

1.问题的解可以分解为几个子问题的解。(子问题:数据规模更小的问题)
2.问题与子问题,除了数据规模不同,求解思路完全一样
3.存在递归终止条件

递归的过程详解

  • 递归的基本过程

首先,我们要了解递归具有堆栈的结构特性:先进后出
当我们在解决问题的过程中发现,这个问题的解,是依赖于一个规模更小的子问题的解,然后我们转向去求一个数据规模小,过程相同的子问题时,发现它的解依赖于规模更小的子问题,之后我们一步一步的求,突然发现最后的子问题的解可以直接求得(这便是递去的过程),然后用这一个子问题的解,来解决与其有关联的上一级子问题的解,最终求得目标问题的解(这便是归来的过程)。
转化为代码中的思想
函数执行到递归函数入口时,就扩充一段完全一样的代码,执行完扩充的代码并return后,继续执行前一次递归函数中递归函数入口后面的代码。

  • 递归中的变量的解释

递去时:每进行一次新的调用,都将创建一批变量,他们将掩盖递归函数前一次调用所创建的变量。可以看出每一级的函数调用都有自己的局部变量,当追踪一个递归函数的执行过程时,必须把不同次调用的变量区分开来,以避免混淆。
如果问题复杂时就有可能有堆栈溢出的风险。
归来时:开始打印输出。然后函数返回,并开始销毁堆栈上的变量值。

  • 关于递归的理解

阅读递归函数最容易的方法不是纠缠于它的执行过程,而是相信递归函数会顺利完成它的任务。如果你的每个步骤正确无误,你的限制条件设置正确,并且每次调用之后更接近限制条件,递归函数总是能正确的完成任务。

返回的过程是隐秘的,但是确实存在的过程。

关于递归的基本知识就这些,下面我们来结合一些代码更加深入的了解递归。

  • 汉诺塔问题(经典)

Description
汉诺塔(又称河内塔)问题是印度的一个古老的传说。

开天辟地的神勃拉玛在一个庙里留下了三根金刚石的棒A、B和C,A上面套着n个圆的金片,最大的一个在底下,其余一个比一个小,依次叠上去,庙里的众僧不倦地把它们一个个地从A棒搬到C棒上,规定可利用中间的一根B棒作为帮助,但每次只能搬一个,而且大的不能放在小的上面。

僧侣们搬得汗流满面,可惜当n很大时这辈子恐怕就很搬完了。

聪明的你还有计算机帮你完成,你能写一个程序帮助僧侣们完成这辈子的夙愿吗?
Input
输入金片的个数n。这里的n<=10。
Output
输出搬动金片的全过程。格式见样例。
Sample
Input
2
Output
Move disk 1 from A to B
Move disk 2 from A to C
Move disk 1 from B to C
Hint
可以用递归算法实现。

第一步:将问题简化–复杂问题求解的基本方法
现在假设A杆上,只有2个圆盘,即汉诺塔有两层,n=2;求解过程如下:

第二步:对于n(n>1)个圆盘的汉诺塔,将n个圆盘分为两部分,“上面n-1个圆盘”看成一个整体(也就是上图中画斜线的部分)
所以就可以写出代码:

#include <iostream>using namespace std;void carry(int n,char a/*起始柱*/,char b/*中间柱*/,char c/*目标柱*/){if(n==1) printf("Move disk %d from %c to %c\n",n,a,c);  //结束条件:子问题中将起始柱上的第一个盘子移动到目标柱上 注意当前的a和c不一定代表A柱子和C柱子 else{carry(n-1,a,c,b);  //将起始柱上的n-1个盘子移动到中间柱子上    1printf("Move disk %d from %c to %c\n",n,a,c);carry(n-1,b,a,c);  //将中间柱子上的n-1个盘子移动到目标柱子上 }
}
int main()
{int n;cin>>n;carry(n,'A','B','C');return 0;}
  • 快速排序
    - 题目链接

所谓快速排序,效率很快,基本思想,两边交替向中间遍历,把大的放一边,小的放一边,再利用递归最终实现排序。

#include <iostream>using namespace std;
const int N=1e5+10;
int a[N];void q_sort(int l,int r){int i=l;int j=r;int k=a[i];if(l>=r)  return ;   //如果左边界大于右边界返回空 else{while(i<j){while(i<j&&a[j]>=k)j--;   //发现一个大于k的值就让该值放在之前k的位置 a[i]=a[j];while(i<j&&a[i]<=k)i++;a[j]=a[i];}a[i]=k;         //把之前提取出来的一个值放到中间 q_sort(l,i-1);   //重复这个过程 q_sort(i+1,r);}
}void print(int n)
{for(int i=0;i<n;i++){if(i==n-1) cout<<a[i]<<endl;else cout<<a[i]<<" ";}
}int main()
{int n;cin>>n;for(int i=0;i<n;i++){cin>>a[i];}q_sort(0,n-1);print(n);return 0;
}
  • 二分查找
    - 题目链接’

二分查找和快排有一些相同的地方,二分查找把要查找的数与数列中中间值进行比较,从而每一次缩小一半。
注意二分查找的序列一定时有序的。

#include <iostream>using namespace std;
const int N=1e7+10;
int a[N];int search(int l,int r,int x){int mid;mid=(l+r)>>1;while(l<=r){if(a[mid]==x) return mid;else if(a[mid]>x) return search(l,mid-1,x);else if(a[mid]<x) return search(mid+1,r,x);}return -1;
}int main()
{int n;cin>>n;for(int i=1;i<=n;i++){cin>>a[i];}int q;int x;cin>>q;while(q--){cin>>x;cout<<search(1,n,x)<<endl;}return 0;}
  • 全排列问题
    - 题目链接
#include <iostream>
#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
const int N = 1e5 + 10;
const int M = 111;
using namespace std;int a[11];///右移元素
void move_r(int l,int r){if(l>=r) return ;int t=a[r];for(int i=r;i>l;i--) a[i]=a[i-1];a[l]=t;
}///左移元素
void move_l(int l,int r){if(l>=r) return ;int t=a[l];for(int i=l;i<r;i++) a[i]=a[i+1];a[r]=t;
}///递归全排列
void perm(int l,int r){if(l==r){for(int i=1;i<=r;i++){if(i==r) cout<<a[i]<<endl;else cout<<a[i]<<",";}}else{for(int i=l;i<=r;i++){swap(a[l],a[i]);move_r(l+1,i);perm(l+1,r);move_l(l+1,i);swap(a[l],a[i]);}}
}int main()
{int n;cin>>n;for(int i=1;i<=n;i++){cin>>a[i];}perm(1,n);return 0;
}

提升:八皇后问题

  • 结语
    我意识到用书面语讲这些题非常的麻烦,而且大家可能也听不懂,所以我就详细的介绍了基本的知识,至于题目,我只是稍微讲了一点思路,加上我给出的代码,大家自己思考出来的效果肯定会更好。

递归算法和过程的详解相关推荐

  1. 【Big Data - Hadoop - MapReduce】通过腾讯shuffle部署对shuffle过程进行详解

    摘要: 通过腾讯shuffle部署对shuffle过程进行详解 摘要:腾讯分布式数据仓库基于开源软件Hadoop和Hive进行构建,TDW计算引擎包括两部分:MapReduce和Spark,两者内部都 ...

  2. goland 方法注释_goland 设置注释模板的过程图文详解

    网上找了一些办法 都没有说到关键点: 梳理一下设置步骤如下,以及避免的坑. 新建文件自动加注释: Preferences | Editor | File and Code Templates 打开go ...

  3. mysql 5.5.18下载_MySQL5.7.18下载和安装过程图文详解

    MySql下载 1.打开官网找到下载路口,这里直接给出下载的地址 2.选择64位版本 3.直接下载 MySql5.7.18.1安装过程 1   .运行安装软件,接受协议 2.选择默认安装 3.下一步到 ...

  4. Nero刻录ISO文件的过程步骤详解

    常见的镜像文件格式有ISO.BIN.IMG.TAO.DAO.CIF.FCD. Nero刻录ISO文件的过程步骤详解(附Nero下载地址无需注册) 刻录ISO文件的软件其实很多--以Nero(德国公司出 ...

  5. 红外接收过程程序详解

    先理解以下知识点: 1.参看程序前,先参阅博文红外NEC协议,否则程序不好理解 2.NEC协议重点查看,代码调制过程,以及逻辑"0",逻辑"1"的高低电平时间特 ...

  6. 【C/C++内功心法】剖析预处理过程,详解其他预处理指令,提升C/C++内功

    文章目录 前言 一.#undef 二.命令行定义 三.条件编译 四.文件包含 1.头文件被包含的方式 2.嵌套文件包含 总结 前言 大家好啊,我是不一样的烟火a,今天我将会为大家详细讲解其他的预处理指 ...

  7. linux子程序标识符,linux过程标识符详解1

    linux进程标识符详解1 每个进程都有一个实际用户标识符和一个实际组标识符,它们永远是启动该进程之用户的用户标识符和组标识符. 进程的有效用户标识符和有效组标识符也许更重要些,它们被用来确定一个用户 ...

  8. 递归算法:兔子繁殖问题详解

    面试题:有一对兔子,从出生后第3个月起每月都生一对小兔子,小兔子长到第3个月后每个月又生一对小兔子,按此规律,假设兔子没有死亡,第一个月有一对刚出生的小兔子,问第20个月有多少只兔子? 解题思路:第一 ...

  9. android sdk安装过程,图文详解Android 3.0 SDK安装教程

    [51CTO编者按]我们已经为喜欢Android 3.0的朋友提供Android 3.0 SDK下载,本文我们将向大家介绍Android 3.0 SDK安装教程,本教程与 玩模拟器需要比较好的电脑配置 ...

最新文章

  1. 走进JavaWeb技术世界7:Tomcat中的设计模式
  2. 如何ping端口_复刻smartbits的国产网络性能测试工具minismb-如何配置Ping报文
  3. 十周后,62%的PHP网站将运行在一个不受支持的PHP版本上
  4. WinForm 自定义控件属性
  5. mysql版本 time类型
  6. 黑龙江对口学计算机上机,2009年黑龙江省职高对口升学计算机应用专业技能试卷十.doc...
  7. Hibernate所用15个jar包
  8. Linux磁盘分区及文件系统格式化和挂载
  9. Ubuntu本地部署Nebula图数据库
  10. 直角三角形 纪中 1385 数学_斜率
  11. lap.lapjv函数cost_limit参数
  12. Axon框架使用指南(二):入门
  13. JavaScript——JSON
  14. linux下贪吃蛇代码,贪吃蛇 linux 程序
  15. UL测试报告办理流程,UL1017测试范围有那些?
  16. java动态生成pdf文件的方法
  17. Linux系统设置用户密码规则(复杂密码策略)方法
  18. 一文了解什么是FTP协议
  19. Linux下最简单的动态域名用法
  20. PhotoScan拼接无人机航拍RGB照片

热门文章

  1. java程序员面试自我介绍
  2. 6.7 广义特征向量与特征空间
  3. VSCode(Visual Studio Code) 在Python中,自动提示函数选中后带括号设置
  4. Matlab优化函数linprog的使用
  5. cad线性标注命令_CAD尺寸标注命令
  6. 使用伪类来实现类似微信群聊的头像样式
  7. 国标28181:jrtplib从编译到使用
  8. 算法竞赛入门经典 开灯问题
  9. return返回值用法
  10. TCP协议和TCP连接