1. 程式人生 > >java:遞迴的結構--基礎篇

java:遞迴的結構--基礎篇

遞迴結構:

   遞迴的基本思想就是“自己呼叫自己”

【示例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

注意:

任何能用遞迴解決的問題也能使用迭代解決。當遞迴方法可以更加自然的反映問題,並且易於理解和除錯,不強調效率問題時,可以採用遞迴。

在要求高效能的情況下儘量避免使用遞迴,遞迴呼叫既花時間又耗記憶體。