簡單的說: 遞歸就是方法本身調用本身,每次調用時傳入不一樣的變量.遞歸有助於編程者解決複雜的問題,同時可讓代碼變得簡潔。算法
我列舉兩個小案例,來幫助你們理解遞歸編程
一、打印問題數組
二、階乘問題google
//輸出什麼?
public static void test(int n) { if (n > 2) { test(n - 1); } System.out.println("n=" + n); } //階乘
public static int factorial(int n) { if (n == 1) { return 1; } else { return factorial(n - 1) * n; }}
三、使用圖解說明遞歸的調用機制spa
一、各類數學問題如: 8皇后問題 , 漢諾塔, 階乘問題, 迷宮問題, 球和籃子的問題(google編程大賽)3d
二、各類算法中也會使用到遞歸,好比快排,歸併排序,二分查找,分治算法等.code
三、將用棧解決的問題-->第歸代碼比較簡潔blog
1)執行一個方法時,就建立一個新的受保護的獨立空間(棧空間)排序
2)方法的局部變量是獨立的,不會相互影響, 好比n變量遞歸
3)若是方法中使用的是引用類型變量(好比數組),就會共享該引用類型的數據.
4)遞歸必須向退出遞歸的條件逼近,不然就是無限遞歸,出現StackOverflowError,死龜了:)
5)當一個方法執行完畢,或者遇到return,就會返回,遵照誰調用,就將結果返回給誰,同時當方法執行完畢或者返回時,該方法也就執行完畢。
迷宮問題:將左上角小球一步一步走到右下角位置。怎麼走?
分析:
一、咱們能夠用一個二維數組map[8][7]表示地圖,i,j 表示從地圖的哪一個位置開始出發 (1,1)
二、若是小球能到 map[6][5] 位置,則說明通路找到.
三、約定: 當map[i][j] 爲 0 表示該點沒有走過 當爲 1 表示牆 ; 2 表示通路能夠走 ; 3 表示該點已經走過,可是走不通
四、在走迷宮時,須要肯定一個策略(方法) 下->右->上->左 , 若是該點走不通,再回溯
實現代碼:
/** * * @param map 表示地圖 * @param i 從哪一個位置開始找 * @param j * @return 若是找到通路,就返回true, 不然返回false */
public static boolean setWay(int[][] map, int i, int j) { if(map[6][5] == 2) { // 通路已經找到ok
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, 3
return false; } } }
public static void main(String[] args) { // 先建立一個二維數組,模擬迷宮 // 地圖
int[][] map = new int[8][7]; // 使用1 表示牆 // 上下所有置爲1
for (int i = 0; i < 7; i++) { map[0][i] = 1; map[7][i] = 1; } // 左右所有置爲1
for (int i = 0; i < 8; i++) { map[i][0] = 1; map[i][6] = 1; } //設置擋板, 1 表示
map[3][1] = 1; map[3][2] = 1; // map[1][2] = 1; // map[2][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); //setWay2(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 1 1 1 1 1 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 1 1 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 1 1 1 1 1 1 小球走過,並標識過的 地圖的狀況 1 1 1 1 1 1 1
1 2 0 0 0 0 1
1 2 2 2 0 0 1
1 1 1 2 0 0 1
1 0 0 2 0 0 1
1 0 0 2 0 0 1
1 0 0 2 2 2 1
1 1 1 1 1 1 1
上面代碼示例 不走策略是 下->右->上->左 ,那麼咱們也能夠改變策略,改爲 上->右->下->左 ,那又怎麼寫,會怎麼走呢。
就是改變上面代碼 if else 順序便可。
這就是簡單運用 遞歸 回溯算法的應用。