递归算法及经典递归实现

article/2025/10/7 3:59:28

递归

递归就是方法自己调用自己,每次调用时传入不同的变量,递归有助于编程者解决复杂的问题,同时可以让代码变得简洁。

递归: 在定义自身的同时又出现了对自身的调用
直接递归函数: 在定义函数体中直接调用自己
间接递归函数: 一个函数经过一系列中间调用语句,通过其他函数调用自己,如P调用Q,Q再调用P

使用 递归算法的 前提有两个:
(1) 原问题可以层层分解为类似的子问题,且子问题比原问题的规模更小。
(2)规模更小的子问题具有直接解

设计递归算法的原则是用自身的简单情况来定义自身设计递归算法的方法是:
(1)寻找分解方法,将原问题转化为子问题求解
(2)设计递归出口,也就是说根据最小的子问题,确定递归终止的条件。

递归过程的实现

递归的过程 ,递归进程和递归退层。
递归进程,也就是说递归的过程 i 到 i+1 层,系统需要做三件工作:
(1)保留本层参数与返回地址;
(2)给下层参数赋值
(3)将程序转移到被掉函数的入口

递归退层:也就是从i+1层到i层,系统也应该完成三件工作
(1)保留被调函数的计算结果
(2)恢复上层参数,也就是释放被调函数的数据区
(3)依照被调函数保存的返回地址,将控制转移回调用函数。、

递归函数的运行,以及递归中进层退层的实现,都需要递归机制的支持。

什么是递归机制?

递归机制支持?

系统设置一个递归工作栈作为递归函数运行使用的存储区,每次递归需要所需信息构成一个工作记录,包括实参,局部变量以及上一层的返回地址。每进入一层递归,就产生一个新的工作记录压入栈顶,每退出一层递归,就从栈顶弹出一个工作记录。

我们可以通过一个简单的阶乘例子来看一下递归调用机制的过程。

package com.recusion;public class printDemo {public static void main(String[] args) {test(4);}public static void test(int n){if (n>2) {test(n-1);}System.out.println("n="+n);}}

当我们的程序执行的时候,首先进入的是主方法。
具体过程我们可以通过虚拟机的调用顺序来看一下详细过程

Java虚拟机主要分成三个部分:
栈空间,堆空间,另外还有一个空间是代码区包括常量
在这里插入图片描述
我们的程序执行到主方法的时候,会首先在栈中开辟一个空间 ,这个空间我们可以叫做main[ 栈 ],在这里面调用了 test(4),根据调用规则,会另外开辟新栈。n=4 ,会进行判断,n>2时,又执行test(3) ,当执行到这里的时候,下面的代码不会执行,仍然会开辟一个新的栈,继续进行判断,test(2),进行判断,然后继续开辟新的栈。继续判断,不符合之后会执行下面的指令。(会首先执行顶级的栈)所以首先会在控制台输出n=2,
执行完之后弹出,继续执行下面的栈。

执行过程:图解如下

在这里插入图片描述

递归调用规则:

  1. 当程序执行到一个方法时,就会开辟一个独立的空间(栈)
  2. 每个空间的数据(局部变量)是独立的,由上面的过程我们可以发现,在每一个栈中,我们都有一个局部变量n=4,n=3…这些局部变量之间是相互独立的。

下面我们来看一下,递归实现阶乘的例子:

	//阶乘问题public static int factorial(int n){if (n == 1) {return 1;}else {return factorial(n-1)*n;}}

递归能解决的问题?

  1. 各种数学问题,如8皇后,汉诺塔,阶乘问题,迷宫问题,球和篮子的问题(Google编程大赛)
  2. 各种各种算法也会用到递归,比如归并排序,二分查找,分治算法等
  3. 将用栈解决的问题,使用递归解决比较简单

递归使用时需要遵守的重要规则

递归需要在遵守的重要规则:

  1. 执行一个方法时,就是创建一个新的受保护的独立空间(栈空间)
  2. 方法的局部变量是独立的,不会相互影响,比如上面例子中的n变量,在每一个栈空间中是独立的。
  3. 如果方法中使用的是引用类型变量,比如说是数组,就会共享该引用类型的数据
  4. 递归必须向退出递归的条件逼近,否则就是无限递归,进入死循环。
  5. 当一个方法执行完毕,或者是遇到return。就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕。

递归经典算法

迷宫问题

迷宫问题说明:
1)小球得到的路径,和程序员设置的找路策略有关,即找路的上下左右的顺序相关
2)再提到小球路径时,可以先使用(下右上左),再改成(上右下左),看看路径是不是有变
3)测试回溯现象

在这里插入图片描述
小球得到的路径,和程序设置的找路径策略有关:即找路的上下左右的顺序有关,在得到小球的路径时,可以先使用 下-右—上–左 ,如果不行再改用 上–右--下–左 , 看看路径是不是有变化,测试回溯现象(我们可以多增加几个墙,这样可以测试回溯现象)。

Q:如何求出最短的路径?

我们可以使用递归进行实现

package com.recusion;public class MiGong {public static void main(String[] args) {//先创建一个二维数组,模拟迷宫//写一个地图,用二维数组表示地图8行7列的二维数组int[][] map = new int[8][7];//在地图中我们使用1表示墙//上下全部置为1for (int i = 0; i < 7; i++) {map[0][i] =1;map[7][i] =1;}//左右全部置为1for(int i = 0; i < 8;i++){map[i][0] = 1;map[i][6] = 1;}map[3][1]=1;map[3][2]=1;//输出地图for(int i = 0;i<8;i++){for(int j=0;j<7;j++){System.out.print(map[i][j]+" ");}System.out.println();}//使用递归回溯给小球找路setWay(map, 1, 1);//输出地图,小球走过,并标识过的地图System.out.println("地图的情况,走过标记过的地图");for(int i = 0;i<8;i++){for(int j=0;j<7;j++){System.out.print(map[i][j]+" ");}System.out.println();}}//使用递归回溯来给小球找路//说明//1. map 表示地图//2. i,j 表示从地图的哪个地方开始出发(1,1)//3. 如果小球能到 map[6][5] 位置,则说明通路找到//4. 约定:当map[i][j] 为0表示该点没有走过,当为1表示墙,当为2时是通路可以走的,为3表示该位置已经走过但是走不通//5. 在走迷宫时需要确定一个策略,也就是一个规则,先走下面,下面不同,再走右面,右面不同在走上面,上面不通,再走左面。如果该点走不通,再回溯/*** 	1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 0 0 0 0 0 1 1 1 1 0 0 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 *//*** map表示地图* i,j表示从 哪个位置开始找* 如果找到通路返回true,如果找不到返回false* @return*/public static boolean setWay(int[][] map,int i,int j){if(map[6][5] ==2 ){return true;}else {if (map[i][j] == 0) {//如果当前点还没有走过//按照策略走map[i][j] = 2;//假定该点可以走通if (setWay(map, i+1, j)) {//先向下走return true;}else if (setWay(map, i, j+1)) {//向右走return true;}else if(setWay(map, i-1, j)){//向上走 return true;}else if(setWay(map, i, j-1)){//向左走return true;}else {//下右上左都走不通,说明这个点是不同的,map[i][j]=3; //标记为此路不同别走return  false;}}else{//如果该点不等于0,map可能是1,2,3  1表示墙,2 走过了  3 是死路return false;}}}	}
递归经典算法八皇后问题:回溯算法

八皇后问题介绍;
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。在8*8格的国家象棋上摆放八个皇后,使其不能互相攻击,即:任意两个皇后都不能处于同一行,同一列,或者是同一斜线上,问有多少中摆法?
解法:我们可以使用回溯法进行解决。

八皇后问题算法思路分析:
(1) 第一个皇后先放第一行第一列
(2) 第二个皇后放在第二行的第二列,然后判断是否OK,即是判断是否冲突,如果不OK,继续放在第二列,第三列,依次把所有的列都放完,找到一个合适的。
(3) 继续第三个皇后,还是第一列,第二列…直到第8个皇后也能放在一个不冲突的位置,算是找到了一个正确解。
(4)当得到一个正确解时,在栈回退到上一个栈时,就会开始回溯,即将第一个皇后,放到第一列的所有正确解全部得到。
(5)然后回头继续将第一个皇后放到第二列,后面继续循环执行1,2,3的步骤

需要说明的是,理论上需要创建一个二维数组表示棋盘,但是实际上可以通过算法,用一个一维数组即可解决问题。
(也就是经过分析,我们先找出一个可能的解,在每一行中填上数组的下标,当前位置表示已经放上皇后, {0,4,7,5,2,6,1,3} 表示提前在此位置上放上八个皇后)
arr[8] = {0,4,7,5,2,6,1,3} 对应的数组下标表示的是第几行,即第几个皇后,arr[i] = val , val表示第i+1个皇后,放在第i+1行的第val+1列。

编程思路:

  1. 定义一个数组,用于保存皇后放置位置的结果,比如 arr = {0, 4 ,7,5,2,6,1,3}

  2. 编写一个方法,放置第n个皇后check(),

  3. 查看当我们放置第n个皇后,就去检测该皇后和前面已经摆放好的皇后冲突

【说明】
【n 表示第n个皇后,n从0开始,arr[i] = val val的值表示第几个皇后,例如 {0,4,7,5,2,6,1,3} 中,4表示第2个皇后在第四列。(通过在这里我们可以发现,arr数组中里面存放的是列数,然后arr[n] 代表的是这个皇后在的列数 )
我们需要进行位置 判断,首先判断两个元素是否是在同一行,然后进行是否在同一行进行判断,但是我们提前定义数组的时候,使用的是一维数组表示位置,按照这种方法定义,我们就可以使用array[i] == array[n] 进行是否值在同一行进行判断。然后还需要判断是否是在同一列进行判断,使用两个位置连线的斜率绝对值等于1进行判断 】

写一个方法,可以将皇后摆放的位置输出
代码如下:


package com.recusion;public class Queen8 {//首先定义表示共有多少个皇后int  max =8;static int count=0;//用于统计总方案数//定义数组array,保存皇后放置位置的结果,比如 arr = {0,4,7,5,2,6,1,3}int[] array = new int[8];public static void main(String[] args) {Queen8 queen8 = new Queen8();queen8.check(0);System.out.println("一共有解法"+count);}// 放置皇后,编写一个方法,放置第n个皇后//特别注意,check是每一次递归时,进入到check中都有一套for循环for (int i = 0; i < max; i++) 因此会有回溯private void check(int n){if (n==max) { //n=8表示放置到第九个皇后,8个皇后已经放好print();return;}//依次放入皇后,并判断是否是冲突的for (int i = 0; i < max; i++) {array[n]=i;//判断当放置第n个皇后到i列时,判断是否是冲突的if (judge(n)) {//接着放n+1个皇后,即开始递归check(n+1); //如果有8个皇后,每一层都会遍历8个列,会产生回溯现象的}//如果冲突,就继续执行array[n] =i ;即将第n个皇后,放置在本行的后移一个位置}}//检测位置  编写方法,当我们放置第n个皇后时,就去检测该皇后是否和前面已经摆放好的皇后位置是否冲突/*** n 表示第几个皇后* @param n* @return*/private boolean judge(int n){for(int i=0;i<n;i++){/*** 说明* 1. array[i] == array[n] 表示判断 第n个皇后是否和前面的n-1个皇后在同一列* 2. Math.abs(n-i)== Math.abs(array[n]-array[i]) 表示判断第n个皇后是否和第i个皇后在同一斜线上* n = 1 放置第二列为1, n=1时,array[1]=1* Math.abs(1-0) ==1 Math.abs(array[n]-array[i]) = Math.abs(1-0) =1* 3. 判断是否在同一行,这一个不用判断,因为for循环中直接限制过了,没有必要进行判断了*/if (array[i]==array[n] || Math.abs(n-i)== Math.abs(array[n]-array[i])) {return false;}	}return true;}//写一个打印数据,也就是皇后放置位置的方法private void print(){count++;for (int i = 0; i < array.length; i++) {System.out.print(array[i]+" ");}System.out.println();}}

http://chatgpt.dhexx.cn/article/YICAyiab.shtml

相关文章

递归算法讲解

原作者&#xff1a;书呆子Rico 《递归的内涵与经典应用》 http://my.csdn.net/justloveyou_ 摘要&#xff1a; 大师 L. Peter Deutsch 说过&#xff1a;To Iterate is Human, to Recurse, Divine.中文译为&#xff1a;人理解迭代&#xff0c;神理解递归。毋庸置疑地&#xff0…

递归算法及经典实例----转载啦~

递归算法及经典递归例子代码实例 递归&#xff08;recursion&#xff09;&#xff1a;程序调用自身的编程技巧。 递归满足2个条件&#xff1a; 1&#xff09;有反复执行的过程&#xff08;调用自身&#xff09; 2&#xff09;有跳出反复执行过程的条件&#xff08;递归出…

递归算法的讲解

原作者&#xff1a;书呆子Rico 《递归的内涵与经典应用》 http://my.csdn.net/justloveyou_ 摘要&#xff1a; 大师 L. Peter Deutsch 说过&#xff1a;To Iterate is Human, to Recurse, Divine.中文译为&#xff1a;人理解迭代&#xff0c;神理解递归。毋庸置疑地&#xff0…

递归算法经典例题及详解

有句话叫递归算法只可意会不可言传&#xff0c;我也领略了&#xff0c;感觉递归算法好神奇&#xff0c;不知不觉的就把工作做完了! 下面这道题也是小编从力扣上看来得&#xff0c;但是关于它是怎样递归的是小编自己想的哦❤️❤️如果有不足&#xff0c;希望大家多多指正&#…

递归算法及经典递归例子代码实现

一、什么叫做递归&#xff1f; 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法&#xff1b; 递归函数就是直接或间接调用自身的函数&#xff0c;也就是自身调用自己&#xff1b; 二、一般什么时候使用递归&#xff1f; 递归时常用的编程技术&#xff0c;其基本…

递归算法(图文详解)

递归算法 一、算法概述 递归算法是一种直接或者间接调用自身函数或者方法的算法。说简单了就是程序自身的调用。二、算法实质 递归算法就是将原问题不断分解为规模缩小的子问题&#xff0c;然后递归调用方法来表示 问题的解。&#xff08;用同一个方法去解决规模不同的问题&am…

递归算法及经典例题详解

大部分人在学习编程时接触的第一个算法应该就是递归了&#xff0c;递归的思想其实很好理解&#xff0c;就是将一个问题拆分为若干个与本身相似的子问题&#xff0c;通过不断调用自身来求解。 但很多新手在实际操作中却很难正确使用到递归&#xff0c;有时面对问题还会有种无从…

几道经典递归算法案例

一&#xff09;递归介绍 定义&#xff1a; 1、在函数体中直接或间接的调用自身的一种方法。 2、必须要有边界值&#xff0c;也就是停止的条件。 头递归&#xff1a;函数调用时不是传递本次计算的结果&#xff0c;而是把当前的调用状态传递&#xff0c;相当于要一直记录上一…

【函数递归】简单递归的5个经典例子,你都会吗?

&#x1f9f8;&#x1f9f8;&#x1f9f8;各位巨佬大家好&#xff0c;我是猪皮兄弟&#x1f9f8;&#x1f9f8;&#x1f9f8; 今天和大家谈谈简单递归&#x1f973;&#x1f973;&#x1f973; &#x1f692;什么是递归 递归的定义&#xff1a; 递归是一种解决问题的有效方…

四个超好用的优质资源搜索网站,海量优质资源等你发现!

在网上找资源的时候总找不到满意的优质资源&#xff1f;今天小编把办公室大佬珍藏多年的四个超好用优质资源搜索网站分享给你&#xff0c;只要你想找&#xff0c;没有找不到的资源&#xff01; 一&#xff0c;学习资料库 学习资料库中有大量的免费学习资料&#xff0c;学习资料…

珍藏多年的技术资源搜索网站——程序员必备

程序员经常需要找一些技术书籍和相关文档&#xff0c;但是通过百度查找往往都是需要各种积分才能够下载&#xff0c;笔者平时的学习中积累几个搜索工具网站&#xff0c;基本上所有需要的技术文档&#xff0c;经典书籍&#xff0c;学习资料&#xff0c;学习视频等等都可以在下列…

在百度上搜不到的资源是在哪找的?就在这些强大的资源搜索网站呀

都说又不懂的问“度娘”最快&#xff0c;但是也有一些东西是在“度娘”哪里也找不到的。那些在百度上搜不到的资源是在哪找的呢&#xff1f;就在这些强大的资源搜索网站呀~ 1.茶杯狐 茶杯狐&#xff0c;它的资源搜索功能很成熟&#xff0c;这里收集了海量的资源可以免费下载&a…

黑科技之资源搜索网站

欢迎加入BIM行业开发交流1群 群号:711844216 一、背景 大家经常会有搜索视频&#xff0c;音乐&#xff0c;PDF&#xff0c;APP等资源的需求&#xff0c;然而通过现有搜索引擎不是很方便找到自己想要的东西&#xff0c;这里笔者推荐几个不错的免费网站&#xff0c;基本上用起来…

超好用的云盘资源搜索网站

超好用的云盘资源搜索网站 云盘资源搜索云云搜索搜百度盘盘搜搜万盘搜索爱挖盘盘搜我的盘 云盘资源搜索 想要的资源轻轻松松一键搞定&#xff0c;让工作生活更轻松。 注*本分享仅供学习参考 云云搜索 http://www.yunyunso.com 搜百度盘 http://www.sobaidupan.com 盘搜…

网盘资源搜索网站

本篇博客总结了百度网盘常用的资源搜索网站。 1.盘搜搜 盘搜搜支持百度云搜索、115网盘、360云盘、华为网盘、新浪微盘等搜索服务&#xff0c;是您工作、学习、娱乐的网盘搜索神器 2.如风搜 如风搜&#xff0c;全网网盘搜索工具。是您工作、学习、娱乐的好助手。找好资源&…

6个超级实用的免费网盘搜索网站分享

因为各种原因&#xff0c;多数网盘搜索网站“寿命”都很短&#xff0c;也有很多百度网盘搜索站点都提高了使用门槛&#xff08;比如付费才能使用&#xff09;。 分享几个自己认为搜索的资料蛮全&#xff0c;到现在&#xff08;2021年&#xff09;为止还能使用的网盘搜索网站。…

我珍藏很久的网盘资源搜索网站和下载神器

摘要&#xff1a;分享几个网盘资源搜索网站和下载神器。 这是「每周分享」的第 17 期。最近有不少新朋友关注&#xff0c;所在再介绍一下这个栏目&#xff0c;每个周末分享一篇 Python 以外的文章&#xff0c;主题涉及&#xff1a;软件、App、PPT、Ps 等几个方面。往期内容你可…

强烈推荐,7个资源搜索网站,从此告别资源付费

前言 周末软件测试自学群很多小伙伴问我&#xff1a;你有啥好的学习资源或者网站没&#xff1f;分享一下可以吗&#xff1f;虽然在国庆期间我整理过&#xff0c;但是趁着周末又给大家整理了一波&#xff0c;完善了不少学习资源&#xff0c;走起~~ 脚本之家 资源很多&#xf…

12款精品网盘资源搜索网站,只有你想不到没有它搜不到的

目录 1.前言 2.网站介绍 3.使用评价 12款精品网盘资源搜索网站&#xff0c;只有你想不到没有它搜不到的 1.前言 今天呢给大家分享几款网盘资源搜索网站&#xff0c;比如盘搜搜、盘盘搜、茶杯狐等&#xff0c;都是非常老牌的网盘资源搜索网站&#xff0c;里面资源丰富且全…

7个资源丰富到爆的搜索网站,没有你找不到的资源!

闲话就不多说了&#xff0c;直接上干货&#xff0c;希望能够帮助到大家&#xff01; IMDB IMDB是互联网电影数据库网站。它包含了所有的电影、电视的内容。如果说豆瓣是国内经常使用的&#xff0c;那么在豆瓣上看不到的东西&#xff0c;使用IMDB就可以查到了。可以使用它来查询…