本文主要讲述java中的递归机制。

示例1,递归代码如下:

public class Recursion01 {
    public static void main(String[] args) {
        T t = new T();
        t.test(4);
    }

}
class T {
    public void test(int n) {
        if(n > 2) {
            test(n-1);
        }
        System.out.println(n);
    }
}

jvm处理递归机制如下图所示:

java递归算法结构 java递归算法代码_递归

运行结果如下:

java递归算法结构 java递归算法代码_System_02

 

示例2,递归代码如下:

public class Recursion01 {
    public static void main(String[] args) {
        T t = new T();
        t.test(4);
    }
}
class T {
    public void test(int n) {
        if(n > 2) {
            test(n-1);
        }else {
            System.out.println(n);
        }
    }
}

jvm处理递归机制如下图所示:

java递归算法结构 java递归算法代码_递归_03

 

运行结果是2。

 注意示例1和示例2的区别。示例1是执行test方法,就会打印当前的n,示例2是做出判断小于或者等于2的打印当前的n。

课堂练习:

1.斐波那契数列

public class Recursion02 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int key = scanner.nextInt();
//        int num = new NumUtils().fun(key);
//        if(num >= 1) {
//            System.out.println("当n="+key+"时,对应的斐波那契数列:"+num);
//        }else {
//            System.out.println("输入数据无效");
//        }
        new NumUtils().Fibonacci(key);
    }

}

class NumUtils {
    // 斐波那契数列中指定索引的值
    public int fun(int n) {
        if(n > 2) {
            return fun(n-1)+fun(n-2);
        }
        if(n == 1 || n == 2){
            return 1;
        }
        return -1;
        
    }
    
    // 打印斐波那契数列
    public void Fibonacci(int n) {
        int a = 0,b = 1,c;
        if(n > 1) {
            System.out.print(1+" ");
            for(int i =1;i<n;i++) {
                c = a + b;
                a = b;
                b = c;
                System.out.print(c +" ");
            }
        }else {
            System.out.println("输入数据有误");
        }    
    }
}

运行结果:

java递归算法结构 java递归算法代码_递归_04

2.猴子吃桃问题:

/* 吃桃规则:每次吃剩余桃子的一半,加一。
 * day10,还有1个桃
 * day9,还有4 = (day10 + 1)*2个桃
 * day8,还有10 = (day9 + 1)*2个桃
 * ...
 */

public class Recursion03 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int day = scanner.nextInt();
        int res = new Monkey().Peach(day);
        if(res != -1) {
            System.out.println("当day="+day+"时,还有"+res+"个桃");
        }else {
            System.out.println("输入天数有误");
        }
        
        
    }
}
class Monkey{
    
    public int Peach(int day) {
        
        if(day == 10) {
            return 1;
        }
        if(day >= 1 && day <10) {
            return (Peach(day + 1)+1)*2;
        }
        
        return -1;
    }
}

 3.迷宫问题

public class Migong {
    public static void main(String[] args) {
        
        int [][] map = new int[8][7];
        
        MiGongGraph graph = new MiGongGraph();
        graph.CreateGraph(map);
        graph.findWay2(map, 1, 1);
        
        System.out.println("===当前地图===");
        for(int  i =0;i<map.length;i++) {
            for(int j = 0;j<map[0].length;j++) {
                System.out.print(map[i][j]+" ");
            }
            System.out.println();
        }
        
        
        
    }

}

class MiGongGraph {
    public void CreateGraph(int[][] map) {
        for(int j = 0;j < map[0].length;j++) {
            map[0][j] = 1;
            map[map.length-1][j] = 1;
        }
        
        for(int i = 0;i<map.length;i++) {
            map[i][0] = 1;
            map[i][map[0].length-1] = 1;
        }
        map[3][1] = 1;
        map[3][2] = 1;
        map[2][2] = 1;
    }
    
    /*
     * 0表示还没有走,不是障碍物, 
     * 1表示障碍物,
     * 2表示走过,无法确定是否是死路
     * 3表示走过,但是走不通,是死路。
     * 
     * 走路的顺序,右->下->上->左
     */
    public boolean findWay(int [][] map,int i,int j) {
        // map[5][6] = 2时,说明已经走出迷宫。
        if(map[6][5] == 2) {
            return true;
        }else {
            // 递归体:
            // 判断当前坐标是否已经走过
            if(map[i][j] == 0) {
                // 没有走过,则将其对应的二维数组的值置为2
                map[i][j] = 2;
                
                // 沿着这个点,按照顺序,走路。
                // 首先是这个点的右边
                if(findWay(map, i, j+1)) {
                    return true;
                // 接着是这个点的下边
                }else if(findWay(map, i+1, j)) {
                    return true;
                // 接着是这个点的上边
                }else if(findWay(map, i-1, j)) {
                    return true;
                // 最后是这个点的左边
                }else if(findWay(map, i, j-1)) {
                    return true;
                }else {
                    // 由于该点的右->下->上->左,都不能走通,则该点是死路,置为3。
                    map[i][j] = 3;
                    return false;
                }
            // 已经走过,不回溯。
            }else {
                return false;
            }
        }
    }
    
    public boolean findWay2(int [][] map,int i,int j) {
        if(map[6][5] == 2) {
            return true;
        }else {
            // 递归体:
            // 判断当前坐标是否已经走过
            if(map[i][j] == 0) {
                // 没有走过,则将其对应的二维数组的值置为2
                map[i][j] = 2;
                
                // 沿着这个点,按照顺序,走路。
                // 首先是这个点的下边
                if(findWay(map, i+1, j)) {
                    return true;
                // 接着是这个点的右边
                }else if(findWay(map, i, j+1)) {
                    return true;
                // 接着是这个点的上边
                }else if(findWay(map, i-1, j)) {
                    return true;
                // 最后是这个点的左边
                }else if(findWay(map, i, j-1)) {
                    return true;
                }else {
                    // 由于该点的右->下->上->左,都不能走通,则该点是死路,置为3。
                    map[i][j] = 3;
                    return false;
                }
            // 已经走过,不回溯。
            }else {
                return false;
            }
        }
    }
}

 4.汉诺塔问题:

汉诺塔规则:a,b,c三柱,将从上往下看由小到大的塔,由a柱搬到c柱。塔仍保持从上往下看,由小到大。

public class HanNoTa {
    public static void main(String[] args) {
        Tower tower = new Tower();
        tower.Method(3, 'A', 'B', 'C');
    }

}

class Tower {
    
    // num是盘子的总数,a,b,c是指代三根柱子。
    public void Method(int num,char a,char b,char c) {
        if(num == 1) {
            System.out.println(a +"->"+c);
        }else {
            // 将汉诺塔分成最后一个盘和上面的盘,两个部分
            // 先将上面的盘,借助c柱,由a柱搬到b柱
            Method(num-1, a, c, b);
            // 此时只剩下最后一个盘,直接由a柱搬到c柱
            System.out.println(a+"->"+c);
            // 还需要将上面的盘,由b柱移动到c柱
//            System.out.println(b+"->"+c);
            // 将上面的盘子,借助a柱,由b柱搬到c柱。
            // 不能直接由b柱到c柱,违背汉诺塔的规则。
            Method(num-1, b, a, c);
            
        }
    }
}