遞歸:指在當前方法內調用本身的現象。算法
遞歸的分類:ui
注意:spa
遞歸致使棧內存溢出的原理:3d
計算 1~ n 的和,n 的累加 = n + (n+1) 的累和,能夠把累和的操做定義成一個方法,遞歸調用。code
實現:對象
1 public class Demo { 2 public static void main(String[] args) { 3 //計算1~num的和,使用遞歸完成 4 int num = 5; 5 // 調用求和的方法 6 int sum = getSum(num); 7 // 輸出結果 8 System.out.println(sum); 9 } 10 /* 11 經過遞歸算法實現. 12 參數列表:int 13 返回值類型: int 14 */ 15 public static int getSum(int num) { 16 /* 17 num爲1時,方法返回1, 18 至關因而方法的出口,num總有是1的狀況 19 */ 20 if(num == 1){ 21 return 1; 22 } 23 /* 24 num不爲1時,方法返回 num +(num‐1)的累和 25 遞歸調用getSum方法 26 */ 27 return num + getSum(num‐1); 28 } 29 }
代碼執行圖解:blog
注意:遞歸必定要有條件限定,保證遞歸可以中止下來,次數不要太多,不然會發生棧內存溢出。
遞歸
階乘:全部小於及等於該數的正整數的積。內存
分析:n! = n * (n-1);get
實現:
1 public class DiGuiDemo { 2 //計算n的階乘,使用遞歸完成 3 public static void main(String[] args) { 4 int n = 3; 5 // 調用求階乘的方法 6 int value = getValue(n); 7 // 輸出結果 8 System.out.println("階乘爲:"+ value); 9 } 10 /* 11 經過遞歸算法實現. 12 參數列表:int 13 返回值類型: int 14 */ 15 public static int getValue(int n) { 16 // 1的階乘爲1 17 if (n == 1) { 18 return 1; 19 } 20 /* 21 n不爲1時,方法返回 n! = n*(n‐1)! 22 遞歸調用getValue方法 23 */ 24 return n * getValue(n ‐ 1); 25 } 26 }
問題:第一我的10,第2個比第1我的大2歲,以此類推,請用遞歸方式計算出第8我的多大?
實現:
1 public int getAge(int n){ 2 /* 3 * 第一我的10,n=1, 結果10 4 * 第二我的12,n=2, 結果10 + 2 getAge(1) + 2 5 * 第三我的14,n=3, 結果10 + 2 + 2 getAge(2) + 2 6 * 7 * 第n我的?,n=?, 結果10 + 2 + 2 ...+ ? getAge(n-1) + 2 8 */ 9 if(n==1){ 10 return 10; 11 }else{ 12 return getAge(n-1) + 2; 13 } 14 }
問題:有n步臺階,一次只能上1步或2步,共有多少種走法?
實現:
1 public long sum(int n){ 2 /* 3 * n==1 1 4 * n==2 2 5 * n==3 最後一步 要麼從第1級跨2步,要麼從第2級跨1步 把走到第1級的走法 + 走到第2級的走法 sum(1) + sum(2) 6 * n==4 最後一步 要麼從第2級跨2步,要麼從第3級跨1步 把走到第2級的走法 + 走到第3級的走法 sum(2) + sum(3) 7 * n==5 最後一步 要麼從第3級跨2步,要麼從第4級跨1步 把走到第3級的走法 + 走到第4級的走法 sum(3) + sum(4) 8 * 9 * n=? 最後一步 要麼從第n-2級跨2步,要麼從第n-1級跨1步 把走到第n-2級的走法 + 走到第n-1級的走法 sum(n-2) + sum(n-1) 10 */ 11 if(n==1 || n==2){ 12 return n; 13 }else{ 14 return sum(n-1) + sum(n-2); 15 } 16 }
分析:多級目錄的打印,就是當目錄的嵌套。遍歷以前,無從知道到底有多少級目錄,因此咱們仍是要使用遞歸實現。
實現1:
1 public class DiGuiDemo { 2 public static void main(String[] args) { 3 // 建立File對象 4 File dir = new File("D:\\aaa"); 5 // 調用打印目錄方法 6 printDir(dir); 7 } 8 public static void printDir(File dir) { 9 // 獲取子文件和目錄 10 File[] files = dir.listFiles(); 11 // 循環打印 12 /* 13 判斷: 14 當是文件時,打印絕對路徑. 15 當是目錄時,繼續調用打印目錄的方法,造成遞歸調用. 16 */ 17 for (File file : files) { 18 // 判斷 19 if (file.isFile()) { 20 // 是文件,輸出文件絕對路徑 21 System.out.println("文件名:"+ file.getAbsolutePath()); 22 } else { 23 // 是目錄,輸出目錄絕對路徑 24 System.out.println("目錄:"+file.getAbsolutePath()); 25 // 繼續遍歷,調用printDir,造成遞歸 26 printDir(file); 27 } 28 } 29 } 30 }
實現2:
1 //listAllSub()方法的功能是列出一個文件或一個目錄及它的下一級 2 public void listAllSub(File dir){ 3 if(dir.isDirectory()){ 4 File[] listFiles = dir.listFiles(); 5 for (File sub : listFiles) {//sub多是一個文件,也多是一個文件夾 6 listAllSub(sub);//遞歸:本身調用本身 7 } 8 } 9 System.out.println(dir); 10 }
實現:
1 public long getLength(File dir){ 2 if (dir != null && dir.isDirectory()) { 3 File[] listFiles = dir.listFiles(); 4 if(listFiles!=null){ 5 long sum = 0; 6 for (File sub : listFiles) { 7 sum += getLength(sub); 8 } 9 return sum; 10 } 11 }else if(dir != null && dir.isFile()){ 12 return dir.length(); 13 } 14 return 0; 15 }
實現:
1 public void deleteDir(File file){ 2 //若是是文件夾,先把它的下一級刪除 3 if(file.isDirectory()){ 4 File[] listFiles = file.listFiles(); 5 //通過這個foreach循環,能夠把file的全部的下一級刪除 6 for (File sub : listFiles) { 7 deleteDir(sub); 8 } 9 } 10 11 //文件夾就變成了空文件夾,就能夠直接刪 12 //若是是文件也能夠直接刪除 13 file.delete(); 14 }