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

递归

文章目录

  • 递归
    • 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 防止随机赋值为3maze[END_ROW][END_COL] = 4;     //终点必须为4 防止随机赋值为3System.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_COLreturn 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 表示墙//上下全部置为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;}//设置挡板 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,3return 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;    //将此皇后的设置为iif (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个皇后摆放的位置对前面每一个皇后的位置都符号规定 返回truereturn 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.hqwc.cn/news/265596.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AMEYA360:大唐恩智浦荣获 2023芯向亦庄 “汽车芯片50强”

2023年11月28日&#xff0c;由北京市科学技术委员会和北京市经济和信息化局指导、北京经济技术开发区管理委员会主办、盖世汽车协办的“芯向亦庄”汽车芯片大赛在北京亦庄成功闭幕。 在本次大赛中 大唐恩智浦的 电池管理芯片DNB1168 (应用于新能源汽车BMS系统) 凭卓越的性能及高…

AidLux:手机/平板上的Linux环境与AI开发利器

AidLux是一个基于ARM架构的跨生态&#xff08;鸿蒙/AndroidLinux&#xff09;一站式智能物联网&#xff08;AIoT&#xff09;应用开发和部署平台&#xff0c;正受到越来越多开发者和用户的青睐。既可以作为手机/平板上的一个Linux环境使用&#xff0c;也可以作为AI开发利器以发…

HCIA-H12-811题目解析(5)

1、【单选题】 以下关于Hybrid端口说法正确的有&#xff1f; 2、【单选题】使用命令"vlan batch 10 20"和"valn batch 10 to 20"&#xff0c;分别能创建的vlan数量是&#xff1f;&#xff08;&#xff09; 3、【单选题】二层ACL的编号范围是&#xff1f;…

厘米级高精度定位系统为什么更倾向于UWB技术?

超宽带&#xff08;Ultra Wide-Band&#xff0c;UWB&#xff09;是一种新型的无线通信技术&#xff0c;根据通信委员会的规范&#xff0c;UWB的工作频带为3.1~10.6GHz&#xff0c;系统-10dB带宽与系统中心频率之比大于20%或系统带宽至少为500MHz。 UWB信号的发生可通过发射时间…

Java预科知识

以下内容是根据狂神的Java说、chatgpt和csdn相关博客&#xff0c;结合自己的理解完成的。 Java了解 基于Java 开发了巨多的平台&#xff0c;系统&#xff0c;工具 构建工具&#xff1a; Ant, Maven, Jekins应用服务器&#xff1a;Tomcat, Jetty, Jboss, Websphere, weblogic…

网络攻击(二)--情报搜集阶段

4.1. 概述 在情报收集阶段&#xff0c;你需要采用各种可能的方法来收集将要攻击的客户组织的所有信息&#xff0c;包括使用社交网络、Google Hacking技术、目标系统踩点等等。 而作为渗透测试者&#xff0c;你最为重要的一项技能就是对目标系统的探查能力&#xff0c;包括获知…

解决IDEA springboot“spring-boot-maven-plugin“报红问题方法

本篇文章小编给大家分享一下解决IDEA springboot"spring-boot-maven-plugin"报红问题方法&#xff0c;文章代码介绍的很详细&#xff0c;小编觉得挺不错的&#xff0c;现在分享给大家供大家参考&#xff0c;有需要的小伙伴们可以来看看。 使用环境 项目环境&#x…

Springboot自定义start首发预告

Springboot自定义start首发预告 基于Springboot的自定义start , 减少项目建设重复工作, 如 依赖 , 出入参包装 , 日志打印 , mybatis基本配置等等等. 优点 模块化 可插拔 易于维护和升级 定制化 社区支持(后期支持) 发布时间 预告: 2023-12-10 预计发布: 2024-1-1 , 元旦首…

【开源】基于Vue.js的就医保险管理系统

文末获取源码&#xff0c;项目编号&#xff1a; S 085 。 \color{red}{文末获取源码&#xff0c;项目编号&#xff1a;S085。} 文末获取源码&#xff0c;项目编号&#xff1a;S085。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 科室档案模块2.2 医生档案模块2.3 预…

【腾讯云 HAI域探秘】借助高性能服务HAI快速学会Stable Diffusion生成AIGC图片——必会技能【微调】

目录 Stable Diffusion基本使用方法 学术加速测试 配置中文插件 Prompt与Negative prompt 采样器说明 人像生成 水光效果 微调的使用 图像生成种子/seed使用 附加/Extra 微调实例测试 图生图微调 ​编辑 使用蒙版微调 Stable Diffusion基本使用方法 环境配置&am…

Raft毕业设计——基于Raft+区块链的共识算法Raft设计与实现(毕业论文+程序源码)——共识算法Raft

基于Raft区块链的共识算法Raft设计与实现&#xff08;毕业论文程序源码&#xff09; 大家好&#xff0c;今天给大家介绍基于Raft区块链的共识算法Raft设计与实现&#xff0c;文章末尾附有本毕业设计的论文和源码下载地址哦。需要下载开题报告PPT模板及论文答辩PPT模板等的小伙…

DELL服务器ESXi 6.7平台配置网卡直通报错

报错信息&#xff1a; 内存设置无效: 内存预留 (sched.mem.min) 应该等于内存大小 尝试勾选内存配置&#xff1a;预留所有客户机内存 报错信息&#xff1a; 模块“DevicePowerOn”打开电源失败。 配置文件中缺少 pciPassthru1.id 条目。 无法启动虚拟机。 尝试&#xff1a…