数据结构与算法—递归及其应用(八皇后,小球出迷宫)

news2024/11/18 1:28:30

递归

文章目录

  • 递归
    • 1.递归应用场景
    • 2.递归的概念
    • 3.递归调用机制
    • 4.递归能解决什么问题
    • 5.递归需要遵守的重要规则
    • 6.递归-迷宫、八皇后问题
      • 6.1 迷宫问题
      • 6.2 八皇后问题

1.递归应用场景

  迷宫问题(回溯),递归(Recursion)

2.递归的概念

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

3.递归调用机制

在这里插入图片描述

图1 递归调用机制

4.递归能解决什么问题

  1. 各种数学问题:8皇后问题,汉诺塔,阶乘问题,迷宫问题,球和篮子的问题
  2. 各种算法中也会使用到递归,比如快排,归并排序,二分查找,分治算法等
  3. 将用栈解决的问题–>递归代码比较简洁

5.递归需要遵守的重要规则

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

6.递归-迷宫、八皇后问题

6.1 迷宫问题

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图2 迷宫问题

之前学韩老师java基础课的时候教过了这个迷宫问题,自己尝试先写了一下,发现还可以

package com.atguigu.recursion;

/**
 * @author 小小低头哥
 * @version 1.0
 * 使用递归解决迷宫回溯问题
 */
public class Maze {

    private static final int ROW = 7;  //行
    private static final int COL = 8;  //列
    private static final int BARRIER = 10;   //障碍数
    private static final int START_ROW = 0; //出生点的行
    private static final int START_COL = 0; //出生点的列
    private static final int END_ROW = ROW - 1;   //终点的行
    private static final int END_COL = COL - 1;   //终点的列

    public static void main(String[] args) {
        maze();
    }
    
    public static void maze(){
        //先创建一个二维数组
        int[][] maze = new int[ROW][COL];
        //0表示没走过 1表示走过且走得通 2表示走过行不通 3表示障碍 4表示终点
        System.out.println("迷宫如下:");
        for (int i = 0; i < ROW; i++) {
            for (int j = 0; j < COL; j++) {
                System.out.print(maze[i][j] + " ");
            }
            System.out.println();
        }
        //随机加入障碍
        for (int i = 0; i < BARRIER; i++) {
            maze[(int) (Math.random() * ROW)][(int) (Math.random() * COL)] = 3;
        }
        maze[START_ROW][START_COL] = 0; //出生点必须为0 防止随机赋值为3
        maze[END_ROW][END_COL] = 4;     //终点必须为4 防止随机赋值为3
        System.out.println("加入障碍后的迷宫如下:");
        for (int i = 0; i < ROW; i++) {
            for (int j = 0; j < COL; j++) {
                System.out.print(maze[i][j] + " ");
            }
            System.out.println();
        }
        if (en(maze, START_ROW, START_COL)) {
            System.out.println("结束后的迷宫如下:");
            for (int i = 0; i < ROW; i++) {
                for (int j = 0; j < COL; j++) {
                    System.out.print(maze[i][j] + " ");
                }
                System.out.println();
            }
        }
    }
    /**
     * @param maze   数组的状态
     * @param nowRow 当前所在迷宫的行
     * @param nowCol 当前所在迷宫的列
     */
    public static boolean en(int[][] maze, int nowRow, int nowCol) {    //出迷宫
        if (nowRow > ROW - 1 || nowCol > COL - 1 || nowRow < 0 || nowCol < 0) {   //说明越界了
            return false;
        }
        if (maze[nowRow][nowCol] == 4) {  //如果到达了终点 或者nowRow = END_ROW nowCol = END_COL
            return true; //行得通
        } else if (maze[nowRow][nowCol] == 3) {    //说明走到了障碍
            maze[nowRow][nowCol] = 2;   //走过行不通
            return false; //行不通
        } else if (maze[nowRow][nowCol] == 2) {
            return false; //行不通
        } else if (maze[nowRow][nowCol] == 1) { //走过的路就不再走了
            return false; //行不通
        } else {
            maze[nowRow][nowCol] = 1;   //设为走过行得通
            System.out.println("行:" + nowRow + "列" + nowCol);
            //先向右走
            if (en(maze, nowRow + 1, nowCol)) {  //向下行得通的话
                return true;
            } else if (en(maze, nowRow, nowCol + 1)) {//向右走行得通的话
                return true;
            } else if (en(maze, nowRow, nowCol - 1)) {   //向左走
                return true;
            } else if (en(maze, nowRow - 1, nowCol)) {  //向上走
                return true;
            } else {
                return false;   //说明死路一条 无路可走
            }
        }
    }
}

老韩写的如下

public static void main(String[] args) {
    miGong();
}

public static void miGong(){
    //先创建一个二维数组 模拟迷宫
    //地图
    int[][] map = new int[8][7];
    //使用1 表示墙
    //上下全部置为1
    for (int i = 0; i < 7; i++) {
        map[0][i] = 1;
        map[7][i] = 1;
    }
    //左右全部置为1
    for (int i = 0; i < 8; i++) {
        map[i][0] = 1;
        map[i][6] = 1;
    }
    //设置挡板 1表示
    map[3][1] = 1;
    map[3][2] = 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();
    }
    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表示从地图那个位置开始走
 * 3. 如果小球能到map[6][5]位置,则说明通路找到
 * 4. 约定:当map[i][j]为0表示该点没有走过 当为1表示墙 2表示通路可走 3表示已经走过,但是走不通
 * 5. 走迷宫时 下->右->上—>左,如果该点走不通 再回溯
 * @param map   表示地图
 * @param i 从哪个位置开始找
 * @param j
 * @return 找到就返回true 否则返回false
 */
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 { //如果map[i][j] != 0,也可能是1,2,3
            return false;
        }
    }
}

6.2 八皇后问题

同样在java基础时有过了解,这次能自己独立写出来,也是很欣慰的。俺的代码如下

package com.atguigu.recursion;

/**
 * @author 小小低头哥
 * @version 1.0
 * 递归解决八皇后问题
 */
public class Queen {
    private static final int SIZE = 8; //棋盘的大小 SIZE * SIZE
    //先创建一个一维数组 用来记录每一列皇后所在的位置
    private static int[] position = new int[SIZE];
    private static int count = 0;//记录下有多少种情况

    public static void main(String[] args) {
        queen(0);
        System.out.println("总共右count=" + count + "方法");
    }

    public static boolean queen(int n) {    //判断第n个皇后的SIZE个位置
        for (int i = 0; i < SIZE; i++) {    //此皇后从摆放的第0行开始摆放
            if (en(position, n, i)) { //如果第n个皇后可以放置在第i个位置
                position[n] = i;    //将此皇后的设置为i
                if (n == SIZE - 1) {   //成功找到一种方式
                    count++;
                    for (int j = 0; j < position.length; j++) {
                        System.out.print(position[j] + " ");
                    }
                    System.out.println();
                    continue;   //直接进行下一个循环
                }
                queen(n + 1); //从下一个皇后继续判断
            }
        }
        //退出循环 说明八个位置都判断完毕
        return false;
    }

    /**
     * 用来判断所摆的第n个皇后是否符合规定
     *
     * @param position 已经摆好的皇后位置的数组
     * @param n        第n个皇后
     * @param k        第n个皇后的位置
     * @return
     */
    public static boolean en(int[] position, int n, int k) {
        for (int i = 0; i < n; i++) {
            if (k == position[i]) { //表示同一行
                return false;
            } else if (position[i] + (n - i) == k || position[i] - (n - i) == k) {   //表示在一个斜线上
                return false;
            }
        }
        //如果退出循环 说明第n个皇后摆放的位置对前面每一个皇后的位置都符号规定 返回true
        return true;
    }
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图3 八皇后问题介绍

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图4 八皇后思路图

韩老师代码如下

private static int count = 0;//记录下有多少种情况
public static void main(String[] args) {
    new Queen().check(0);
    System.out.println("一共有count=" + count + "解法");
}

//编写一个方法 放置第n个皇后
private void check(int n) {
    if (n == max) {   //说明皇后已经放好了
        print();
        count++;
        return;
    }

    //依次放入皇后 并判断是否冲突
    for (int i = 0; i < max; i++) {
        //先把当前这个皇后,放入到该行的第一列
        array[n] = i;
        //判断方放置第n个皇后是否冲突
        if (judge(n)) {
            //接下来判断第n+1个皇后
            check(n + 1);
        }
        //如果冲突继续循环 直到完成八个位置的循环摆放
    }
}

//查看当放置第n个皇后 就去检测该皇后是否和前面已经摆放的皇后冲突
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])表示是否是同一列
        if (array[i] == array[n] || Math.abs(n - i) == Math.abs(array[n] - array[i])) {
            return false;
        }
    }
    return true;
}

//写一个方法 可以将皇后摆放的位置输出
private void print() {
    for (int i = 0; i < array.length; i++) {
        System.out.print(array[i] + " ");
    }
    System.out.println();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1303080.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

互联网数据传输原理 |OSI七层网络参考模型

网络模型 OSI 网络参考模型&#xff0c;仅作为参考&#xff0c;也就是说OSI网络实际中并不使用。我们只是把OSI网络模型作为参考&#xff0c;在网络出现问题的时候&#xff0c;可以从一个宏观的整体去分析和解决问题。而且搭建网络的时候也并不一定需要划分为7层 但是当今互联…

面向AOP(2)spring

我是南城余&#xff01;阿里云开发者平台专家博士证书获得者&#xff01; 欢迎关注我的博客&#xff01;一同成长&#xff01; 一名从事运维开发的worker&#xff0c;记录分享学习。 专注于AI&#xff0c;运维开发&#xff0c;windows Linux 系统领域的分享&#xff01; 本…

C语言使用malloc函数模拟开辟二维数组(带分析)

系列文章目录 &#x1f31f; 个人主页&#xff1a;古德猫宁- &#x1f308; 信念如阳光&#xff0c;照亮前行的每一步 文章目录 系列文章目录&#x1f308; *信念如阳光&#xff0c;照亮前行的每一步* 当我们使用malloc函数来模拟创建一个二维数组时&#xff0c;我们需要理解…

VBA信息获取与处理:在EXCEL中随机函数的利用

《VBA信息获取与处理》教程(版权10178984)是我推出第六套教程&#xff0c;目前已经是第一版修订了。这套教程定位于最高级&#xff0c;是学完初级&#xff0c;中级后的教程。这部教程给大家讲解的内容有&#xff1a;跨应用程序信息获得、随机信息的利用、电子邮件的发送、VBA互…

Caching the Application Engine Server 缓存应用程序引擎服务器

Caching the Application Engine Server 缓存应用程序引擎服务器 Application Engine caches metadata just like the application server. This caching enhances performance because a program can refer to the local cache for any objects that it uses. 应用程序引擎…

客服工单系统推荐:哪个最适合您?

客服工单系统是企业的业务过程的“保安”&#xff0c;保障业务流程的顺利开展&#xff0c;同时保障企业客户的权益。所以&#xff0c;市场上有越来越多的企业纷纷配置了客服工单系统&#xff0c;以提供客户服务质量。 对于有购买意向的中小企业来讲&#xff0c;需要关注哪些因…

OpenKylin安装idea

Web和客户端都支持Linux了&#xff0c;一个为了Linux上调试程序方便&#xff0c;一个为了把开发环境彻底支持Linux&#xff0c;在Linux上安装idea运行代码&#xff0c;之前剔除Maven那些的优点就来了&#xff0c;在OpenKylin上我只要安装idea和jdk就能正常运行代码了。 首先从…

小程序嵌套H5

小程序嵌套H5 使用Hbuild x开发H5页面项目里面使用了js-sdk工具包H5发布完成之后生成URL。新建一个小程序空项目&#xff0c;填写小程序的appid。本地调试的时候如果报错无法打开该网页&#xff0c;那么需要勾选先的不校验。发布体验版本需要注意下面的两个配置点。 使用Hbuild…

CV计算机视觉每日开源代码Paper with code速览-2023.12.6

点击计算机视觉&#xff0c;关注更多CV干货 论文已打包&#xff0c;点击进入—>下载界面 点击加入—>CV计算机视觉交流群 1.【基础网络架构&#xff1a;Transformer】Rejuvenating image-GPT as Strong Visual Representation Learners 论文地址&#xff1a;https://a…

你好!堆排序【JAVA】

目录 1.简单介绍 2.大小顶堆 3.基本思想 4.基本思路 4.代码实现数组转化堆 5.代码排序 6.总代码测试 1.简单介绍 堆排序是一种基于堆数据结构的排序算法&#xff0c;其核心思路是利用堆这种特殊的数据结构来对数据进行排序。堆是一种完全二叉树&#xff0c;并且满足父节…

建筑可视化数据大屏汇总,UI源文件(PC端大屏设计)

酷炫的大屏设计让数据更好的展现&#xff0c;方便业务人员分析数据&#xff0c;辅助领导决策。现在分享大屏Photoshop源文件&#xff0c;以下为部分截图示意。 划重点&#xff1a;文末可获得完整素材包~ 01 科技建筑平台数据可视化 02 建筑公司可视化数据汇总平台 03 深蓝…

算法Day27 身材管理(三维背包)

身材管理&#xff08;三维背包&#xff09; Description Input Output Sample 代码 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner new Scanner(System.in);int n scanner.nextInt(); // 输入n的值int money sca…

TrustZone之完成器:外围设备和内存

到目前为止,在本指南中,我们集中讨论了处理器,但TrustZone远不止是一组处理器功能。要充分利用TrustZone功能,我们还需要系统其余部分的支持。以下是一个启用了TrustZone的系统示例: 本节探讨了该系统中的关键组件以及它们在TrustZone中的作用。 完成器:外围设备…

Docker创建镜像的方式---Dockerfile

Dockerfile可以创建自定义镜像。包括配置文件&#xff0c;挂载点&#xff0c;对外暴露的端口&#xff0c;设置环境变量。 Docker创建镜像的方式 1、 基于已有镜像创建&#xff1a;根据官方提供的镜像源&#xff0c;创建镜像。然后拉起容器。是一个白板智能提供基础的功能&…

【收获】成长之路

目录 一、前言二、计算机方面三、专业知识方面四、总结 一、前言 四年&#xff0c;对于一个人的成长来说&#xff0c;是一个相当重要的阶段。在这段时间里&#xff0c;我经历了许多挑战、收获了许多成就&#xff0c;也在不断地成长和改变。回首这四年的点点滴滴&#xff0c;我深…

mybatis多表映射-延迟加载,延迟加载的前提条件是:分步查询

1、建库建表 create database mybatis-example; use mybatis-example; create table t_book (bid varchar(20) primary key,bname varchar(20),stuid varchar(20) ); insert into t_book values(b001,Java,s001); insert into t_book values(b002,Python,s002); insert into …

牛客网(二叉树)

https://www.nowcoder.com/practice/4b91205483694f449f94c179883c1fef?tpId60&&tqId29483&rp1&ru/activity/oj&qru/ta/tsing-kaoyan/question-ranking 这个题目和leetcode比起来就是有一些不一样&#xff0c;需要我们自己来写接口函数&#xff0c;所以…

Linux系统编程(一):基本概念

参考引用 Unix和Linux操作系统有什么区别&#xff1f;一文带你彻底搞懂posix Linux系统编程&#xff08;文章链接汇总&#xff09; 1. Unix 和 Linux 1.1 Unix Unix 操作系统诞生于 1969 年&#xff0c;贝尔实验室发布了一个用 C 语言编写的名为「Unix」的操作系统&#xff0…

鸿蒙原生应用/元服务开发-Stage模型能力接口(二)

ohos.app.ability.AbilityConstant (AbilityConstant)一、说明 AbilityConstant提供Ability相关的枚举&#xff0c;包括设置初次启动原因、上次退出原因、迁移结果、窗口类型等。本模块首批接口从API version 9开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口…

stm32学习总结:3、Proteus8+STM32CubeMX+MDK很有搞头

stm32学习总结&#xff1a;3、Proteus8STM32CubeMXMDK很有搞头 文章目录 stm32学习总结&#xff1a;3、Proteus8STM32CubeMXMDK很有搞头一、前言二、资料收集三、实际案例-点灯1、Proteus8安装2、Proteus创建stm32F013C6项目并添加外围LED电路3、STM32CubeMX配置F103C6引脚生成…