java:遞迴的結構--基礎篇
阿新 • • 發佈:2019-01-06
遞迴結構:
遞迴的基本思想就是“自己呼叫自己”
【示例1-1】
public static void main(String[] args) { a(); } static void a(){ System.out.println("a"); a(); }
如上示例,將會報錯java.lang.StackOverflowError的錯吳,錯誤的原因:是由於a方法一直呼叫a方法,而沒有釋放,導致記憶體不足,才產生的錯誤。
遞迴結構分為兩部分:
1.定義遞迴頭:解答:什麼時候不呼叫自身方法,如果沒有頭,將陷入死迴圈,也就是遞迴的結束條件。
2.遞迴體:解答:什麼時候需要呼叫自身的方法
【示例1-2】遞迴基本結構
public static void main(String[] args) { a(); } static int count = 0; static void a(){ count++; System.out.println("a"); if(count < 5){ a(); }else{ return; } }
【示例1-3】遞迴:解析
public static void main(String[] args) { System.out.printf("%d階乘的結果:%s%n",5,factoria(5)); factoria(5); } static long factoria(int n){ if(n == 1){ return 1; }else{ return n * factoria(n - 1); } }
執行結果:
5階乘的結果:120
遞迴執行分析圖:
遞迴缺陷:
簡單的程式是遞迴的優點之一,但遞迴的呼叫會佔大量的系統棧堆,記憶體耗用多,在遞迴呼叫層次多時速度要比迴圈慢的多,所以在使用遞迴時需慎重。
【示例1-4】遞迴執行效率與普通迴圈效率對比
public static void main(String[] args) { long d1 = System.currentTimeMillis(); System.out.printf("%d階乘的結果:%s%n",10,factoria(10)); long d2 = System.currentTimeMillis(); System.out.printf("遞迴費時:%s%n",d2-d1); factoria(5); factoriaLong(10); } static long factoria(int n){ if(n == 1){ return 1; }else{ return n * factoria(n - 1); } } static long factoriaLong(int a){ long d3 = System.currentTimeMillis(); long res = 1; while(a > 1){ res *= a * (a - 1); a -= 2; } long d4 = System.currentTimeMillis(); System.out.println(res); System.out.printf("普通迴圈費時:%s%n",d4-d3); return res; }
執行結果:
10階乘的結果:3628800
遞迴費時:31
3628800
普通迴圈費時:1
注意:
任何能用遞迴解決的問題也能使用迭代解決。當遞迴方法可以更加自然的反映問題,並且易於理解和除錯,不強調效率問題時,可以採用遞迴。
在要求高效能的情況下儘量避免使用遞迴,遞迴呼叫既花時間又耗記憶體。