數據結構與算法--遞歸(recursion)

遞歸的概念

簡單的說: 遞歸就是方法本身調用本身,每次調用時傳入不一樣的變量.遞歸有助於編程者解決複雜的問題,同時可讓代碼變得簡潔。算法

遞歸調用機制

我列舉兩個小案例,來幫助你們理解遞歸編程

一、打印問題數組

二、階乘問題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,就會返回,遵照誰調用,就將結果返回給誰,同時當方法執行完畢或者返回時,該方法也就執行完畢。

遞歸應用場景

迷宮問題(回溯), 遞歸(Recursion)

 

迷宮問題:將左上角小球一步一步走到右下角位置。怎麼走?

分析:

一、咱們能夠用一個二維數組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 順序便可。

這就是簡單運用 遞歸 回溯算法的應用。

相關文章
相關標籤/搜索