【小白學演算法】10.遞迴的呼叫機制、使用時要注意的規則

把蘋果v咬哭發表於2021-04-23

簡單來說,遞迴就是自己呼叫自己,在每次呼叫時傳入不同的變數。遞迴有助於解決複雜的問題,同時讓程式碼變得簡潔。
在之前的文章中,對遞迴有過簡單的介紹,現在進一步瞭解下遞迴的呼叫機制。

一、遞迴的呼叫機制

先上一段簡單的遞迴呼叫的程式碼:

package recursion;

public class RecursionTest {
    public static void main(String[] args) {
        test(4);
    }

    public static void test(int n) {
        if (n > 2) {
            test(n - 1);
        }
        System.out.println("n=" + n);
    }
}

可以看到,在main方法裡,執行test(4),當滿足n>2的條件時,test()會繼續呼叫test(),直到不滿足遞迴條件,列印出n的值。
執行結果其實也很容易想到:

n=2
n=3
n=4

Process finished with exit code 0

執行結果倒不是重點了,現在藉著這段程式碼再加張圖,看下遞迴的呼叫機制。

圖中所示就是在執行程式碼的過程中,jvm中發生的一些事情。不過這裡宣告一下,關於jvm的某些描述可能並不是很準確,這裡只是輔助理解記憶。

  1. 首先,在執行main方法時,會在棧裡開闢一個main方法的棧幀。
    當main方法裡呼叫test方法時,又會壓入一個棧幀,也就是入棧。當方法沒執行結束時,是不會出棧的。
    所以,執行test(4),會繼續壓入一個棧幀(紅色箭頭)。
  2. test(4)裡,經過判斷會繼續呼叫test(3),於是繼續壓入一個棧幀。
  3. test(3)裡,經過判斷會繼續呼叫test(2),於是繼續壓入一個棧幀。
  4. test(2)裡,經過判斷,不再遞迴,於是執行了print程式碼,列印出n的值為2。
    方法執行完了就會出棧(黃色箭頭),回到test(3)
  5. test(3)列印出n的值為3,繼續出棧,回到test(4)
  6. test(4)列印出n的值為4,main方法執行結束,退出程式。

所以,程式碼執行的結果就是2,3,4

二、使用遞迴需要知道的點

  1. 執行一個方法時,會建立一個新的受保護的獨立空間。比如上面的棧幀。
  2. 方法的區域性變數是獨立的,不會相互影響。比如上面每次遞迴時候的變數n
    但是,如果方法中使用的是引用型別變數,那會共享該引用型別。比如,引用一個陣列。
  3. 重點:遞迴必須向退出遞迴的條件逼近,否則就無限遞迴,最終棧溢位StackOverflowError
  4. 當方法執行完畢,或者遇到return,就會返回。遵守誰呼叫,就將結果返回給誰。
    比如上圖中最上面的棧幀test(2)執行結束後,就返回到呼叫它的test(3)

相關文章