2020-08-26

递归算法(基于JAVA实现)

递归算法,在计算机科学中是指一种通过重复将问题分解为同类的子问题而解决问题的方法。
递归式方法可以被用于解决很多的计算机科学问题,因此它是计算机科学中十分重要的一个概念。
绝大多数编程语言支持函数的自调用,在这些语言中函数可以通过调用自身来进行递归。
计算理论可以证明递归的作用可以完全取代循环,因此在很多函数编程语言(如Scheme)中习惯用递归来实现循环。

递归能解决的问题:

例如:
(1)数学上:汉诺塔问题、8皇后问题、阶乘问题、迷宫问题等。
(2)算法上:归并排序、快速排序、二分查找等。
(3)对于解决栈的问题

递归的注意事项:

(1)递归必须向退出递归的条件接近,否则就会无限递归(StackOverflowError)
(2)如果方法中引用的是类型变量,那么就会共享此数据。
(3)递归方法中的局部变量是独立的,不会相互影响。
(4)执行一个递归方法时,就要创建一个独立的栈空间。
(5)当一个递归方法执行完毕时,就返回,遵循谁调用,将结果返回给谁,此时该方法执行完毕。

一、利用递归思想解决8皇后问题。

八皇后问题,是由国际西洋棋棋手马克斯·贝瑟尔于1848年提出的问题,是回溯算法的典型案例。
问题表述为:在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、
同一列或同一斜线上,问有多少种摆法?

解决思路(回溯算法):

(1)先把第一个棋子放在第一行第一列
(2)第二个皇后放在第二行第一列,此时需要进行判断此皇后与n-1前面的皇后进行判断是否冲突。
若冲突则放在第二列,第三列。。。。直到找到一个合适的点。
(3)继续把第三个皇后放在第三行第一列……进行冲突判断,直至找到合适的 。
(4)直到找到第八个棋子与前面不冲突,此时得到一个正解。
(5)然后进行回溯,到第一个棋子放在第一行第二列,重复(1)(2)(3)(4)步骤,最后得到总共的解决方案。

以下为实现代码:

package com.java;

import static sun.misc.Version.print;

public class Queen8Demo {
    public static void main(String[] args) {
        Queen queen = new Queen();
        queen.check(0);
        queen.display();
    }
}
class Queen
{
    int max = 8;//8皇后
    int[] array = new int[max];
    int count = 0;//记录有多少种解法
    int judgeCount = 0;//记录需要处理多少遍
    //编写一个检索方法,检索每次放入的皇后是否冲突
    public void check(int n)
    {
        if (n == 8)//此时说明8皇后放置已经成功
        {
            print();
            return;
        }
        //遍历8次,依次判断是否会冲突
        for (int i = 0; i < max; i++) {
            array[n] = i;
            if (judge(n))//此时不冲突
            {
                //然后继续放后面的皇后
                check(n + 1);
            }
            //否则继续遍历
        }
    }

    public boolean judge(int n)
    {
        judgeCount++;
        //判断第n个皇后 与 前面n-1个皇后是否在同一列上
        //判断第n个皇后 与 前面n-1个皇后是否在同一斜线上
        for (int i = 0; i < n; i++) {
            if (array[i] == array[n] || Math.abs(n-i) == Math.abs(array[n] - array[i]))
                return false;
        }
        return true;
    }

    //打印皇后位置
    public void print()
    {
        count++;//记录有多少种解法
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i] + "\t");
        }
        System.out.println();
    }
    public void display()
    {
        System.out.println("解决方法有:" + count + "种。");
        System.out.println("一共处理了" + judgeCount + "遍");
    }

}

二、迷宫找路问题

此时定义一个二维数组作为迷宫地图,需要从某个点出发,直至找到最后的出口。
0表示没有走过的路,1表示墙,2表示可以走的路,3表示走过的路,但走不通。
package com.java;

import java.util.Scanner;

public class Maze {
    public static void main(String[] args) {
        int line,column;//定义行与列
        System.out.println("请输入要绘画的行与列");
        Scanner scanner = new Scanner(System.in);
        line = scanner.nextInt();
        column = scanner.nextInt();
        //把迷宫画出来,1为障碍
        int[][] map = new int[line][column];
        //给外层添加墙壁
        for (int i = 0; i < line; i++) {
            map[i][0] = 1;
            map[i][6] = 1;
        }
        for (int i = 0; i < column; i++) {
            map[0][i] = 1;
            map[7][i] = 1;
        }

        //设置障碍
        map[5][1] = 1;
        map[3][2] = 1;
        //找路
        setWay(map,3,6);

        //遍历地图
        for (int i = 0; i < column; i++) {
            for (int j = 0; j < line; j++) {
                System.out.print(map[i][j] + "\t");
            }
            System.out.println();
        }
    }

    //定义查找迷宫道路 下-右-上-左
    //i,j表示地图的开始位置
    //当map[i][j] = 0表示该点没有走过,可以走,当为1时为墙
    //当为2时表示路可以走,当为3时表示该点已经走过,但走不通
    public static boolean setWay(int[][] map, int i, int j) {
        if (map[6][5] == 2)//说明道路已经找到
        {
//            System.out.println("已找到路程,此时花了的次数为:"+count);
            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))//向左走
                {
                    return true;
                }
                else {//此路走不通
                    map[i][j] = 3;
                    return false;
                }
            } else
            {
                return false;
            }
        }
    }

}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值