递归java实现——基本思路及示例

递归算法

  • 一、基本概念
  • 二、基本思路
  • 三、代码示例
    • (一)八皇后问题代码实现

一、基本概念

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

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

递归能够解决的问题

  1. 问题解法按递归算法实现:八皇后、汉诺塔、阶乘、迷宫、球和篮子问题
  2. 数据的定义是按递归定义的。如Fibonacci函数。
  3. 数据的结构形式是按递归定义的。如二叉树、广义表等。
  4. 其他算法:快排、归并排序、二分查找、分治算法等。

二、基本思路

  在解决问题时,如果我们发现待解决的问题是需要我们进行重复的操作,而只是操作的内容或者参数发生规律或者周期性改变时,就可以考虑使用递归来解决。

需要注意:

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

三、代码示例

(一)八皇后问题代码实现

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

思路分析:
(1)先把第一个皇后放置在第一行的第一列。
(2)然后把第二个皇后放置在第二行的的各列,找到一个不冲突的位置
(3)继续放置下一个皇后,在第三行找到一个不冲突的位置进行放置
(4)直到将八皇后放置完毕得到一个正确解,再回退到上一个栈,开始回溯,即得到第一个皇后放在第一行第一列的所有正确解。
(5)然后继续找出第一个皇后在第一行第二列的所有正确解。以此类推,直到得到第一个皇后在八个位置上的所有正确解。

1. 首先定义一个类来定义一些基本的属性

/**
 * @author dankejun
 * @create 2020-04-21 17:40
 */
public class Queue8 {
    //共有多少个皇后
    int MAX = 8;
    //定义数组,存放皇后的位置的结果
    int arr[] = new int[MAX];
    static int count = 0;//统计解法
    }

2.接着定义需要用到的方法:摆放皇后、判断是否冲突、输出结果
在摆放皇后 void check(int n)方法里,就用到了递归的解法。判断第n个皇后位置不冲突时,就递归的调用check(n+1)方法放置第n+1个皇后,直到皇后都防止好。如果发现第n+1个皇后在下一行的8列都发生冲突,则回溯到第n个皇后的位置进行重新摆放。

    /**
     * 放置皇后
     * @param n 从第n个皇后开始放置
     */
    private void check(int n) {
        if (n == MAX) {//已经放置好了皇后
            print();//输出皇后位置
            return;
        }
        //依次放入皇后,并判断是否冲突
        for (int i = 0; i < MAX; i++) {
            //先把当前皇后n,放到该行的第一列
            arr[n] = i;
            //判断是否冲突
            if (juge(n)) {//不冲突
                check(n + 1);
            }
            //如果冲突,就继续执行arr[n] = i;,即将此皇后放到本行的下一列
        }
    }
    /**
     * 查看放置第n个皇后时,检测该皇后是否和前面已经摆放的皇后冲突
     * @param n 表示第n个皇后
     * @return
     */
    private boolean juge(int n) {
        for (int i = 0; i < n; i++) {
            //arr[i] == arr[n]判断第n个皇后是否和第i和皇后在同一列
            //Math.abs(n - i) == Math.abs(arr[n] - arr[i]判断第n个皇后是否和第i个皇后在同一斜线
            if (arr[i] == arr[n] || Math.abs(n - i) == Math.abs(arr[n] - arr[i])) {
                return false;
            }
        }
        return true;
    }

    //输出皇后摆放的位置
    private void print() {
        count++;
        for (int i = 0; i < arr.length; i++) {
            System.out.print((arr[i]+1) + " ");
        }
        System.out.println();
    }

3. 测试一下

 public static void main(String[] args) {
        Queue8 queue8 = new Queue8();
        queue8.check(0);
        System.out.println("一共有" + count + "种解法");
    }

测试结果:
递归java实现——基本思路及示例_第1张图片

你可能感兴趣的:(java算法,算法,java,数据结构,编程语言)