二話不說,先上代碼
java
- public class TestRecursion{
-
- public static void fun(int i){
- if(i > 0){
- i--;
- fun(i);
- System.out.print(i);
- }
- System.out.print(" ok ");
- }
- public static void main(String args[]){
- fun(10);
- }
- }
public class TestRecursion{
//遞歸方法
public static void fun(int i){
if(i > 0){
i--;
fun(i);
System.out.print(i);
}
System.out.print(" ok ");
}
public static void main(String args[]){
fun(10);
}
}
這段代碼看似簡單,其中的奧祕你卻未必盡知。
首先.什麼是遞歸?相信你們都知道,就是方法直接或間接地調用自身。
要想深刻理解遞歸,得從棧的角度去看待方法間的調用。
先來看一個簡單的例子:
小程序
- public void a(){}
- public void b(){
- System.out.println("Hello");
- a();
- System.out.println("boy");
- }
public void a(){}
public void b(){
System.out.println("Hello");
a();
System.out.println("boy");
}
方法b()調用了方法a(),此時程序再也不順序執行,而是發生跳轉。CPU首先將下一條機器指令的地址以及相關的參數信息壓入棧中,而後程序跳轉到a()的方法體中。當a()方法返回時,CPU會執行出棧操做,取出上一次存儲的機器指令的地址以及參數信息,即System.out.println("boy")(固然了,System.out.println()不是一條機器指令,而是被翻譯成多條機器指令)
遞歸方法也是一個道理,只不過,調用者與被調用者是同一個方法。
遞歸與循環的有些類似,但又大相徑庭。循環沒有方法間的調用關係,也就沒有指令地址的壓棧、出棧,它僅僅指令地址的改變。
現貼出TestRecursion小程序的輸出結果:
ide
- ok 0 ok 1 ok 2 ok 3 ok 4 ok 5 ok 6 ok 7 ok 8 ok 9 ok
ok 0 ok 1 ok 2 ok 3 ok 4 ok 5 ok 6 ok 7 ok 8 ok 9 ok
分析調用過程:fun(10)->fun(9)->fun(8)->fun(7)->fun(6)->fun(5)->fun(4)->fun(3)->fun(2)->fun(1)->fun(0)
咱們倒過來分析:當i=0時,首次不知足i>0的條件,因此首先打印「ok"。而後fun(0)結束了,返回到fun(1)中,執行調用fun(0)的下一條語句,即System.out.print(i),此時i=0.確定有的朋友不明白爲何這裏i=0.看下面的代碼
url
- public static void fun(int i){
- if(i > 0){
- i--;
- fun(i);
- System.out.print(i);
- }
- System.out.print(" ok ");
- }
public static void fun(int i){//此時i==1
if(i > 0){//yes
i--; //此時i==0了
fun(i);//即fun(0)
System.out.print(i);//i==?
}
System.out.print(" ok ");
}
繼續分析:打印"0",又打印" ok ",以後fun(1)方法結束了,返回到fun(2)調用fun(1)的下一條語句,System.out.print(i),此時i=1,依次類推。
spa