Java实现简单的递归操作方法实例

前言

在数据结构算法设计中,或者一个方法的具体实现的时候,有一种方法叫做“递归”,这种方法在思想上并不是特别难,但是实现起来还是有一些需要注意的。虽然对于很多递归算法都可以由相应的循环迭代来代替,但是对于一些比较抽象复杂的算法不用递归很难理解与实现。

递归分为直接递归和间接递归,就简单分享一下两个小的直接递归。

对于递归的概念,其实你可以简单的理解为自己定义自己,记得小时候看过一部电视剧《狼毒花》,里面主角叫做“常发”,但是个文盲,老师问他叫什么,他说“常发”。“哪个常?”“常发的常啊!”“哪个发?”“常发的发啊!”结果第二节课老师就让一群小朋友一起喊“常发的常,常发的发,傻瓜的傻,傻瓜的瓜”。言归正传,显然在多数情况下递归是解释一个想法或者定义的一种合理方法。在思想上递归类似于数学中曾经学过的数学归纳法。

递归的实现:

递归的实现要注意有两点:一个递归的选项和一个非递归的选项,后者成为基础情形(base case)。基础情形是递归的终结情形,没有基础情形或者处理不好都会导致无穷递归,这是我们不想要的结果。递归实现起来最关键的是处理好基础情形。 结合具体事例在说一下递归回溯的过程。

下边来写两个小程序:

1、爬楼梯算法:已知一个楼梯有n个台阶,每次可以选择迈上一个或者两个台阶,求走完一共有多少种不同的走法。

方法如下:

递归函数有返回值的比没有返回值的麻烦一点,因为一个函数只有一个返回值,但是递归还要求有基础情形的存在,所以还必须有if判断来终止递归。所以在每一个if或者else后边都有一个return,这样保证函数在任何一种情况下都有且仅有一个返回值。

分析一下这个算法:

A:如果有0个台阶,那么有0种走法,这个不用多说;

B:如果有1个台阶,那么有1种走法;

C:如果有2个台阶,那么有2种走法(一次走1个,走两次;一次走两个);

以上的B和C就是基础情形。

D:接下来就是递归了,如果台阶数目多于2个,那么首先第一步就有两种选择:第一次走1个,或者第一次走两个。这样除了第一次后边的走法就有了两种情形:climbStairs(n-1)和climbStairs(n-2)。这样一直递归下去,直到出现到了基础情形(即n=1或n=2的情形),递归到这个地方(基础情形),然后开始回溯 ,这就是所说的和递归密切相关的“回溯”了。回溯,顾名思义就是从结果倒着回去,找到整个过程,进而分析这个路径或者说是实现的过程。

需要注意的是,这个算法实现思路上简单,但是复杂度并没有降低,还牵扯回溯保存堆栈问题(其实递归的设计尽量避免这种嵌套两个的递归方式(climb(n)中包含climb(n-1)和climb(n-2)),这种操作会使得堆栈开辟空间随着n的增大以指数型增长,最终程序很容易崩溃),而且在台阶数目多到一定数量的时候会越界(走法次数会超出int的范围),所以递归程序很大程度上就是思想实现设计上简单理解一些。

下边是源代码:

package leetcode;

public class ClimbStairs {
//	**************************************************************
	public int climbStairs(int n) {
  int i=1;
		 if(n<=0)
			return 0;
		 if(n==1){
			 return i;
		 }
		 if(n==2){
			 i++;
			 return i;
		 }
		 else
			 return climbStairs(n-1)+climbStairs(n-2);
 }
//**************************************************************
 	 public static void main(String []args){
		 ClimbStairs cs=new ClimbStairs();
		 int a =cs.climbStairs(4);
	 	 System.out.println(a);
	 }

}

然后还有几个比较典型的递归问题:比如说迷宫问题,或者最经典的汉诺塔问题,下边都给出源码,大家一块儿学习一下。

汉诺塔问题:一次只能移动一个盘子;不能把大盘子放在小盘子上;除去盘子在两个柱子之间移动的瞬间,盘子必须都在柱子上。(在这三点要求下把盘子从起始柱子A全部移动到目标柱子C上)

代码如下:

基础情形:n==1的时候终止递归,进行回溯。

public class HanNuoTower {
	public void tower(int n,char s,char m,char e)//n个塔从s经过m最终全部移动到e
	{
		if(n==1)
			move(s,e);
		else
		{
			tower(n-1,s,e,m);
			move(s,e);
			tower(n-1,m,s,e);
		}
	}
	public void move(char s,char e){
		System.out.println("move "+s+" to "+e);
	}
	public static void main(String []args){
		HanNuoTower hnt =new HanNuoTower();
		hnt.tower(4,'A','B','C');
	}

}

迷宫走法:二维数组构成一个迷宫,1表示通路,0表示不通,找到一条路径从起始点(traverse函数的参数)到终点(右下角点)。

基础情形:row=grid.length-1&&column=grid[0].length-1时done=true;

public class Maze {
	private final int TRIED=3;
	private final int PATH=7;

	private int [][] grid={	{1,1,1,0,0,1,0,1,0,0},
										{0,0,1,1,1,0,0,0,0,0},
										{1,0,1,0,0,0,1,1,1,1},
										{1,1,1,1,1,0,0,0,1,1},
										{0,0,0,0,1,1,1,0,0,0},
										{1,0,1,0,1,0,0,1,0,0},
										{1,0,0,1,1,1,1,1,1,1}		};
	public boolean traverse(int row,int column){
		boolean done =false;
		if(valid(row,column))
		{
			grid[row][column]=TRIED;
			if(row==grid.length-1&&column==grid[0].length-1)
				done=true;
			else
			{
				done=traverse(row+1,column);//down
				if(!done)
					done=traverse(row,column+1);//right
				if(!done)
					done=traverse(row-1,column);//up
				if(!done)
					done=traverse(row,column-1);//left
			}
			if(done)
				grid[row][column]=PATH;
		}
		return done;
	}
	private boolean valid(int row,int column){
		boolean result=false;
		if(row>=0&&row<grid.length&&column>=0&&column<grid[row].length)
			if(grid[row][column]==1)
				result=true;
		return result;
	}
	public String toString(){
		String result="\n";
		for (int row=0;row<grid.length;row++){
			for(int column=0;column<grid[row].length;column++){
				result +=grid[row][column]+" ";
			}
			result+="\n";
		}
		return result;
	}
	public static void main (String []args){
		Maze maze=new Maze();
		System.out.println(maze);
		if(maze.traverse(0, 0))
			System.out.println("The maze was successfully travelled!");
		else
			System.out.println("There is no possible path.");
		System.out.println(maze);
	}

}

还有一个九连环的操作,有兴趣的话可以一起看看。Java递归解决九连环问题

总结

到此这篇关于Java实现简单的递归操作的文章就介绍到这了,更多相关Java递归操作内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java算法之递归算法计算阶乘

    本文为大家分享的java算法计算阶乘,在学习Java课程时经常会遇到求阶乘问题,今天接跟大家一起探讨一下 代码如下: package com.xu.main; import java.util.Scanner; public class P9 { static long fact(int n) { if(n <= 1) { return 1; } else { return n * fact(n - 1); } } public static void main(String[] args) {

  • Java递归算法的使用分析

    递归算法是一种直接或者间接地调用自身的算法.在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解. 问题1:一列数的规则如下: 1.1.2.3.5.8.13.21.34 ,求第30位数是多少?使用递归实现 复制代码 代码如下: public class FibonacciSequence {    public static void main(String[] args){        System.out.println(Fribonacci(9))

  • java 递归深入理解

    一.递归函数,通俗的说就是函数本身自己调用自己... 如:n!=n(n-1)! 你定义函数f(n)=nf(n-1) 而f(n-1)又是这个定义的函数..这就是递归 二.为什么要用递归:递归的目的是简化程序设计,使程序易读 三.递归的弊端:虽然非递归函数效率高,但较难编程,可读性较差.递归函数的缺点是增加了系统开销,也就是说,每递归一次,栈内存就多占用一截 四.递归的条件:需有完成任务的语句,需满足递归的要求(减小而不是发散) 五.递归进阶: 1.用递归算n的阶乘: 分析:n!=n*(n-1)*(

  • 快速排序算法原理及java递归实现

    快速排序 对冒泡排序的一种改进,若初始记录序列按关键字有序或基本有序,蜕化为冒泡排序.使用的是递归原理,在所有同数量级O(n longn) 的排序方法中,其平均性能最好.就平均时间而言,是目前被认为最好的一种内部排序方法 基本思想是:通过一躺排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列. 三个指针: 第一个指针称为pivotkey指针(枢轴),第二个指

  • java 用递归获取一个目录下的所有文件路径的小例子

    复制代码 代码如下: private List<String> ergodic(File file,List<String> resultFileName){        File[] files = file.listFiles();        if(files==null)return resultFileName;// 判断目录下是不是空的        for (File f : files) {            if(f.isDirectory()){// 判

  • Java无限级树(递归)超实用案例

    如下所示: @Override public String getEmployeeBysup(String employeeID) { String str=""; str = getEmployeeBysupSelas(employeeID, str); return str.substring(0, str.lastIndexOf(",")); } @Override public String getEmployeeBysupSelas(String empl

  • java递归菜单树转换成pojo对象

    复制代码 代码如下: package com.cjonline.foundation.authority.pojo;import java.util.ArrayList;import java.util.Collections;import java.util.Iterator;import java.util.List;import org.apache.log4j.Logger;import com.cjonline.foundation.util.CheckNullEmpty;/** *

  • Java递归算法经典实例(经典兔子问题)

    题目:古典问题:3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 分析:首先我们要明白题目的意思指的是每个月的兔子总对数:假设将兔子分为小中大三种,兔子从出生后三个月后每个月就会生出一对兔子, 那么我们假定第一个月的兔子为小兔子,第二个月为中兔子,第三个月之后就为大兔子,那么第一个月分别有1.0.0,第二个月分别为0.1.0, 第三个月分别为1.0.1,第四个月分别为,1.1.1,第五个月分别为2.1.2,第六个月分别为3.2.3,第

  • Java 跳出递归循环问题解决办法

    使用异常跳出循环 1.如果方法体内含有需要抛出异常的对象,让方法直接抛出异常,不要在方法体内捕获 public void xxxx() throws Exception 2.如果方法体内不含有需要抛出异常的对象 class Test { static class StopMsgException extends RuntimeException { } public static void main(String args[]) { try { run(0); } catch (StopMsgE

  • Java递归遍历树形结构

    废话不多说了,直接给大家贴代码,具体代码如下所示: //菜单树形结构 public JSONArray treeMenuList(JSONArray menuList, int parentId) { JSONArray childMenu = new JSONArray(); for (Object object : menuList) { JSONObject jsonMenu = JSONObject.fromObject(object); int menuId = jsonMenu.ge

随机推荐