Java 初識遞迴
阿新 • • 發佈:2022-05-07
Java 遞迴
- 什麼是遞迴
- 遞迴: 即在成員方法內呼叫自身
- 遞迴的優點
- 能用簡潔的程式碼解決複雜的問題
- 遞迴的缺點
- 對記憶體的消耗大
- 遞迴的應用場景
- 當我們要獲取一個結果,但是這個結果依賴與上一步一樣操作所得到的結果,才能進行運算時,可以使用遞迴
- 回溯:有多個選擇,但不確定哪個是正確的可以使用遞迴的回溯現象進行逐一嘗試
遞迴的使用
即在成員方法內呼叫自身方法
public class ...... { // 例項化物件 Recursion func = new Recursion(); // 呼叫 function 方法 func.function(10); } class Recursion { public void function (int number) { if (number == 1) { return; } System.out.println(number); } }
遞迴的注意事項
- 因為
JVM
會為每個呼叫的方法單獨開闢一個臨時棧,每呼叫一次開闢一個,只要方法不結束,這個棧就會一直存在,所以遞迴的層次不能太多次。 - 遞迴一定要有出口,即:退出條件
- 遞迴必須擁有最少一個形參
遞迴的經典應用
階乘
public class ...... { // 例項化物件 Recursion object = new Recursion(); // 呼叫 階層 方法 object.factorial(10); } class Recursion { /** * @param number 階乘層數 * @return 階層結果 */ public int factorial (int number) { if (number == 1) { // 當 number = 1 時退出遞迴 return 1; } // 利用上一層的結果 來計算 // factor...(number - 1) * 2 // factor...(number - 1) * 3 // factor...(number - 1) * 4...... return factorial(number - 1) * number; } }
遞迴的回溯現象
回溯也是遞迴的常用方法,如:
- 當前有n個方案,方案1、方案2、方案3......,我們不確定哪個方案是能解決問題
- 先嚐試方案1 方案1能通過執行後續程式碼
- 如不同通過嘗試方案2以此類推
如尋路案例
public class ...... { public static void main (String[] args) { Map mapObject = new Map(); int map[][] = mapObject.genMap(8, 7); System.out.println("尋路結果如下:\n" + mapObject.findWay(map, 1, 1)); // 列印尋路結果 new Arrayss().printArrays(map); } } class Map { // 用於記錄出口位置 int exportX; int exportY; /** * 生成地圖 * @param row 行 * @param column 列 * 0 表示可走 * 1 表示障礙物 */ public int[][] genMap (int row, int column) { int map[][] = new int[row][column]; // 生成一個四邊圍的地圖 for (int rows = 0; rows < row; rows++) { for (int columns = 0; columns < column; columns++) { if (rows == 0 || rows == row - 1 || columns == 0 || columns == column - 1) { map[rows][columns] = 1; } } } // 隨機生成1~10個障礙物 for (int randomCount = 1; randomCount <= (int)(Math.random() * 10) + 1; randomCount++) { // 隨機指定可活動行 int randomRow = (int)(Math.random() * (row - 2)) + 1; // 隨機指定可活動列 int randomColumn = (int)(Math.random() * (column - 2)) + 1; // 隨機位置生成障礙物 map[randomRow][randomColumn] = 1; } // 記錄隨機出口位置 exportX = (int)(Math.random() * (column - 2)) + 1; exportY = (int)(Math.random() * (row - 2)) + 1; map[exportY][exportX] = 2; // 列印地圖未尋路前 new Arrayss().printArrays(map); map[exportY][exportX] = 0; return map; } /** * @param map 地圖 * @param x 當前位置x座標 * @param y 當前位置y座標 * @return boolean 此位置是否可通 */ public boolean findWay (int map[][], int x, int y) { switch (map[exportY][exportX]) { // 如果 出口位置等於2 // 說明程式已經走到出口位置,返回true case 2: return true; // 處理當前位置不為出口位置的情況 default: switch (map[y][x]) { // 當前位置為 0 說明可進行嘗試 case 0: // 假定當前位置可從上下左右其中一個走同 map[y][x] = 2; // 嘗試向下尋路 if (findWay(map, x, y+1)) { return true; } // 嘗試向右尋路 else if (findWay(map, x+1, y)) { return true; } // 嘗試向左尋路 else if (findWay(map, x-1, y)) { return true; } // 嘗試向上尋路 else if (findWay(map, x, y-1)) { return true; } // 如果四個方向都不通 else { // 將當前位置記錄為 3 並返回false map[y][x] = 3; return false; } default: // 當前位置不為 0 說明是死路返回false並退出 return false; } } } } class Arrayss { public void printArrays (int array[][]) { for (int twoDimensional = 0; twoDimensional < array.length; twoDimensional++) { for (int index = 0; index < array[twoDimensional].length; index++) { System.out.print(array[twoDimensional][index] + " "); } System.out.println(); } } }