資料結構與演算法--遞迴
阿新 • • 發佈:2020-09-16
遞迴(Recursion)
簡單的說,遞迴就是方法自己呼叫自己,每次呼叫時傳入不同的變數,有助於開發者解決複雜問題同時使程式碼更加簡潔!
遞迴小案例
階乘問題:
public static int factorial(int n){
if(n == 1){
retern 1;
}else{
retern factorial(n - 1) * n;
}
}
遞迴應用場景
1.各種數學問題:八皇后,漢諾塔,迷宮,階乘,球和籃子 等等; 2.各種演算法中使用遞迴:快速排序,歸併排序,二分查詢,分治演算法 等等 3.把用棧解決的問題使用遞迴替代可以簡化程式碼;
遞迴遵守的規則
1.執行一個方式時,就會建立一個新的**受保護的獨立空間(棧)**;
2.方法的區域性變數是獨立的,不會相互影響;
3.如果方法中使用的是**應用資料型別,就會共享應用資料的資料**;
4.遞迴**必須向退出遞迴的條件靠近**,否則就是個死迴圈,最終出現StackOverflowError異常;
5.當一個方法執行完畢,或者**遇到return**,就會返回,遵守誰呼叫就把結果返回給誰,當方法執行完畢或者返回,改方法也就執行完畢;
回溯
回溯是一種優搜尋法,按選優條件向前搜尋,達到目標,擔當搜尋到某一步時發現原來得選擇並不優或打不到目標,就退回一步重新選擇
回溯與遞迴的區別
遞迴是一種演算法結構。遞迴出現在子程式中,形式上表現為直接或間接地自己呼叫自己。
回溯是一種演算法思想,是使用遞迴實現的。回溯的過程類似於窮舉法,但回溯有“剪枝”(自我判斷)的功能;
八皇后問題
八皇后問題是一個古老而著名的問題,是回溯演算法的典型案例:要求:在8x8的國際象棋上擺放八個皇后,使
其不能互相攻擊,即:任意兩個皇后都不能出於同一行,同一列,同一斜線上,問共有多少種擺法!!
思路:
1.第一個皇后先放在第一行第一列 2.第二個皇后放在第二行第一列,然後判斷是否ok,不ok,放在第二列,第三列... ,依次放完所有列,直到找到一個合適的; 3.第三個皇后放在第三行第一列,第二列 ... ,直到第八個皇后也找到不衝突的位置。得到正確解。 4.當得到正確解之後,棧退回到上一個棧時,就開始回溯,即將第一個皇后放到放到第一列的所有正解全部得到。 5.然後返回繼續將第一個皇后放到第二列,後面繼續迴圈執行1,2,3,4的步驟。 public class Queue8 { //定義一個max:表示共有多少個皇后 int max = 8; int[] array = new int[max]; //儲存皇后放置的結果 static int count = 0; static int judgeCount = 0; public static void main(String[] args) { Queue8 queue8 = new Queue8(); queue8.check(0); System.out.printf("共有%d種解法\n",count); System.out.printf("判斷衝突的次數:%d次",judgeCount); } //放置第n+1個皇后 private void check(int n){ if (n == max){ print(); return; } //依次放入皇后,並判斷是否衝突 for (int i = 0; i < max; i++) { //先把當前的皇后n 放到該行的第一列 array[n] = i; //判斷放置第n個皇后到i列時,是否衝突 if (judge(n)){ //放n+1個皇后,(遞迴) check(n+1); } //如果衝突,就繼續執行array[n]=i(將第n個皇后放置在本行後移的一個位置) } } //檢視當我們放置第n個皇后,就去檢測該皇后是否和前面已經擺放好的衝突 /** * * @param n 表示第n個皇后 * @return */ private boolean judge(int n){ judgeCount++; for (int i = 0; i < n; i++) { /** * array[i] == array[n]:表示判斷 第n個皇后和前面的 n- 1皇后是否在同一列 * Math.abs(n-i) == Math.abs(array[n]-array[i]:表示判斷第n個皇后是否和第i個皇后在同一斜線 */ if (array[i] == array[n] || Math.abs(n-i) == Math.abs(array[n]-array[i])){ return false; //衝突 } } return true; //表示不衝突 } //將皇后擺放的位置輸出 private void print(){ count++; for (int i = 0; i < array.length; i++) { System.out.print(array[i]+" "); } System.out.println(); }}
結果:
解法共有 92 種,judge共執行 15720 次!