数据结构之递归案例一

什么是递归?

顾名思义,所谓递归就是一个函数(或方法)自己调用自己,最简的如下:

public void text() {
        text();
}
  • 就是这么简单,但是一定要给这个递归函数一个出口,不然就会无限循环下去,最后的结果就是OutOfMemory(内存溢出),如果是在main函数中调用的话,就会出现栈空间已满的错误。
  • 如何给一个递归的方法写一个出口呢?
    只要在递归的过程中,有一个方法有一条return 语句,也就是有一个递归方法不再进行递归就会退出了。
    我们给上方法添加一个返回的条件;
private int count = 0;
/*
*   每次让count累加,当它等于4时,就返回,这样就能这个递归函数了
*/
public void text() {
   if (count == 4) {
      return;
   }
      count++;
      text();
}

递归有什么用?

1.最著名的就是裴波那契数列

有如下问题:假设第一个月有一对刚出生的兔子,第二个月兔子进入成熟期,我三个月开始生育小兔子,而一对成熟的兔子会在每月生育一对小兔子,兔子永远不会死去。。。n月后会有多少只兔子
可以很容易地使用穷举来计算刚开始的几个月的兔子数

月份 1 2 3 4 5 6 7
兔子对数 1 1 2 3 5 8 13
  • 使用递归来解决这个问题的思路分析:

很容易得到一个算式就是:
当n=0时,有0对兔子;
当n=1时,有1对兔子;
当n=2时,有1对兔子,因为它是第三个月才开始生小兔子的
当n>2时,F(n)=F(n-1)+F(n-2)

当有了上面的式子后,我们就很容易地写出了如下代码:

public static int brithNew(int n) {
        if (n < 0) {
            return -1;
        }
        if (n == 0) {
            return 0;
        }
    //这个其实就是递归退出的条件,因为n一直的在递减
        if (n <= 2) {
            return 1;
        }

        return brithNew(n-1)+brithNew(n-2);
}

2.使用递归解决迷宫问题

先使用二维数组定义一个迷宫,有如下约定:

  • 先使用0来表示这个迷宫中的所有位置
  • 使用1来表示最外层的墙
  • 使用2来表示这个点位已经走过了,而且是通的
  • 使用3来表示这个点位已经走过,但是不通
    定义的迷宫如下图:

    图中红色的部分表示墙,要从左上角移动到右下角,先使用二维数组定义一个迷宫。
private static void init(int[][] maze) {
        //定义所有的墙
        for (int i = 0; i < 10; i++) {
            maze[0][i] = 1;
            maze[7][i] = 1;
        }
        for (int i = 0; i < 8; i++) {
            maze[i][0] = 1;
            maze[i][9] = 1;
        }

        maze[3][1] = 1;
        maze[3][2] = 1;
        maze[3][3] = 1;
        maze[5][3] = 1;
        maze[5][4] = 1;

        maze[5][5] = 1;
        maze[4][5] = 1;
        maze[3][5] = 1;
        maze[2][5] = 1;
        maze[1][5] = 1;

        maze[2][7] = 1;
        maze[3][7] = 1;
        maze[4][7] = 1;
        maze[5][7] = 1;
        maze[6][7] = 1;
    }

打印下这个数组,就和上边的图片一样,如下:

然后就开始找寻路径,具体有如下规则

  • 每一个点都有下、右、上、左四条路径可选择,这个顺序是可以改变的;
  • 更换这四个顺序,就会有不同的结果,所以可以试着更换这四个顺序来求现最短路径
  • 当走到这个点时,我们先假设这个路径点是正确的,就是先给它赋值为2
  • 每一个小递归退出的条件就是终点的值为2,即maze[9][7]==2
  • 如果这个条路不通,就将当前这个点设置为3
private static boolean searchRoute(int maze[][], int x, int y) {
        int i = maze.length;
        int j = maze[0].length;

        if (maze[i - 2][j - 2] == 2) {
            //目标点的值为2,就说明这条路已经走完了
            return true;
        } else {
            if (maze[x][y] == 0) {//为0说明这这条可走,而且没有走过
                maze[x][y] = 2;
                //按照下、右、上、左的顺序
                if (searchRoute(maze, x + 1, y)) {//向下
                    return true;
                } else if (searchRoute(maze, x, y+1)) {//向右
                    return true;
                } else if (searchRoute(maze, x - 1, y)) {//向上
                    return true;
                } else if (searchRoute(maze, x, y - 1)) {//向左
                    return true;
                } else {
                    maze[x][y] = 3;
                    return false;
                }
            } else {
                return false;
            }
        }
    }

上边用到的打印数组的代码为:

public static void printlnArr(int arr[][]) {
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                System.out.print(arr[i][j] + "\t");
            }
            System.out.println();
            System.out.println();
        }
    }

关注作者公众号,学习Java不迷路

原文地址:https://www.cnblogs.com/Lyn4ever/p/12169283.html

时间: 2024-10-13 13:37:32

数据结构之递归案例一的相关文章

JS高级---递归案例

递归案例 递归案例: 求一个数字各个位数上的数字的和:  123   --->6 ---1+2+3 //递归案例:求一个数字各个位数上的数字的和: 123 --->6 ---1+2+3 function getEverySum(x) { if (x < 10) { return x; } //获取的是这个数字的个位数 return x % 10 + getEverySum(parseInt(x / 10)); } console.log(getEverySum(1364)); 递归案例:

数据结构入门——递归

数据结构是学习编程路上的重要一步,也为以后学习算法打下基础,数据结构又称算法与数据结构,与算法密不可分,是计算机软件专业的核心课程,其重要性不言而喻. 递归分为递推与回归两个过程,递归的优点是容易理解,方便编程,可以解决很多问题,缺点是需要不断的调用递归,时间效率慢,空间占用大. 递归示例: # include <stdio.h> int f(int n) { //printf("1"); n = f(n); return n; //return f(n); //递归,必须

数据结构之递归

定义:一个函数直接或间接调用自己 递归需要满足的三个条件: 1.递归必须有一个明确的中止条件 2.该函数所处理的数据规模必须在递减 3.这个转化必须是可解的 循环和递归: 递归: 易于理解 速度慢,存储空间大 循环: 不易理解 速度快,存储空间小 举例: 1.求阶乘 这一个所知道的信息就是  n! = n * (n-1)!; 这个时候,我们可以让程序不停的调用这个方法以便达到这种所谓的结果. 1 #include <stdio.h> 2 long sum(long n); 3 long sum

c语言数据结构:递归的替代-------回溯算法

1.要理解回溯就必须清楚递归的定义和过程. 递归算法的非递归形式可采用回溯算法.主要考虑的问题在于: 怎样算完整的一轮操作. 执行的操作过程中怎样保存当前的状态以确保以后回溯访问. 怎样返回至上一次未执行的操作. 2.贴代码表现: 先序遍历二叉树: BTNode *FindNode(BTNode *b,ElementType x) { //在二叉树中查找值为x的结点 BTNode *p; if (b==NULL) return NULL; else if (b->Element==x) retu

递归案例

一般定义 程序调用自身的编程技巧称为递归( recursion). 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量.递归的能力在于用有限的语句来定义对象的无限集合.一般来说,递归需要有边界条件.递归前进段和递归返回段.当边界条件不满足时,递归前进:当边界条件满足时,递归返回. 注意: (1) 递归就是在过程或函数里调用自

算法—递归案例—一段神奇的代码

public class test { public static void main(String[] args) { f(3,3); } public static void f(int n,int k){ if(n==0||k==0) return ; if(n>0){ f(n-1,k); System.out.println("n=="+n+" k=="+k); } if(k>0){ f(n,k-1); System.out.println(&q

算法设计方法:递归的内涵与经典应用

摘要: 大师 L. Peter Deutsch 说过:To Iterate is Human, to Recurse, Divine.中文译为:人理解迭代,神理解递归.毋庸置疑地,递归确实是一个奇妙的思维方式.对一些简单的递归问题,我们总是惊叹于递归描述问题的能力和编写代码的简洁,但要想真正领悟递归的精髓.灵活地运用递归思想来解决问题却并不是一件容易的事情.本文剖析了递归的思想内涵,分析了递归与循环的联系与区别,给出了递归的应用场景和一些典型应用,并利用递归和非递归的方式解决了包括阶乘.斐波那契

递归与迭代_1 2016.4.21

迭代乃人工,递归方神通 To interate is human,to recurse,divine 一.定义 (1) 迭代 是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果 每一次对过程的重复称为一次"迭代",而每一次迭代得到的结果会作为下一次迭代的初始值 (2) ① 程序调用自身的编程技巧称为递归( recursion) 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量

函数-递归调用

一.什么是递归调用 递归调用:在函数调用过程中,直接或间接地调用了函数本身,这就是函数的递归调用1.递归的优点 递归函数的优点是定义简单,逻辑清晰.理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰. 使用递归函数需要注意防止栈溢出.在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧.由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出.可以试试fact(1000): 2.递归的缺点 解