2012-10-18 27 views
1

應該我認爲,我在編程一個很好的背景,但今天我碰到的東西,讓我質疑來的東西。下面是代碼:遞歸函數打印,我認爲它不是

public class Recursive{ 
public static void main(String[] args) { 
    func(10);   
} 

static void func(int x) 
{ 
    if(x > 0) 
    { 
     func(x/2); 
     System.out.print(x % 2);  // I thought the code won't reach here ever 
    }     
} 

}

在我看來,這個代碼應該不顯示任何信息。但是當我編譯它時,它實際上打印了1010。如果System.out.print(x % 2)是在func(X/2)之前寫的,那麼這將是有道理的,但現在看起來不正確。對此有何解釋?

回答

1
func(x/2);  ----------------> // Statement # 1 
System.out.print(x % 2); ------> // Statement # 2 

Statement # 2本來Unreachable Block有你Statement # 1

Recursive function calls返回的func(x/2) call值存儲在stack。因此,對於每次調用,都會創建一個stack entry,存儲當前的呼叫,並轉向下一個呼叫。

現在,當達到基本條件時,stack開始roll-back,通過彈出該函數的前一個狀態,然後最終到達它開始的位置。

現在每func呼叫從棧中彈出後,將繼續執行在function其中最後func()調用做(Statement # 2 in this case)下一條語句,並完成後,該函數返回輪流調用堆棧一個功能。(注: - 如果你代替func(x/2)return func(x/2),那麼代碼將不會執行下一條語句,而是立即在堆棧中的下一個函數把控制權因此Unreachable Code

因此,在最後的聲明

System.out.print(x % 2); 

將得到執行,當stack完全排空,控制返回到

func(x/2) 

函數調用,這是一個t堆棧的底部。


所以,你的遞歸是這樣的: -

堆棧: -

func(x/8) --> Base condition 
func(x/4)^
func(x/2)^
func(x)  --> First invocation 

假設x/8是基本條件。所以,當func(x/8)完成執行,下一條語句OT執行的是: -

System.out.println(x % 2) - >這裏x的值是original-x/8

,則此函數從堆棧中彈出,並且控制返回到下一個在堆疊功能: - func(x/4),然後執行下一條語句: -

System.out.println(x % 2) - >再次x這裏是original-x/4

等等。然後最終,System.out.println(x % 2)original-x

+0

@Abraham。我希望這種解釋能讓你理解幕後發生的事情。 –

+0

是的。非常感謝你們所有人的詳細解釋。 – Abraham

2

到FUNC該呼叫被進行,然後它打印X%2。

如果你會使用,另一方面回報FUNC(X/2),print語句將永遠不會達到。

1

必須做出第二次調用FUNC,然後一個調用已經完成,它會工作下來堆棧來完成原來的功能。

你需要查找的基本遞歸論。

http://en.wikipedia.org/wiki/Recursion_(computer_science)。

如上所述,使用 return func(x/2) 會從堆棧中刪除該函數,因此永遠不會到達函數的末尾。

2

它很簡單。起初,函數func()的值爲10. 它在內部檢查是否10> 0.因爲它調用func(5 /*10/2 = 5*/)。

然後自5> 0,在內部它調用FUNC(2)。這是因爲.5的截斷。 func(2/2 /*= 1*/)被調用並執行。 然後,調用函數func(0),它返回。當它返回,打印語句與1%2 = 1。即內部返回執行,並與2%,再次執行打印語句2 = 0。再次返回並與參數的5%2 = 1,再次執行打印語句。返回最後一個打印語句再次執行打印0。

0

hmmmm執行在我以爲它不會打印任何東西,但跟蹤代碼給我說1010是寫答案,因爲我們從來沒有改變x的值,我的意思是我們正在做的第一眼在x上的操作,但我們正在存儲。所以這就是爲什麼它是1010而不是什麼。

好技巧問題

1

打印「1」和「0」的行爲是絕對正確的。

雖然你的x>嚴格大於0,你會用新的x = int(x/2)進行更深的遞歸,因爲x是一個整數。

當x < = 1時,您將擁有x/2 == 0,因此遞歸會停止,您將開始打印剩下的x/2。

你的情況:

f(10)->f(5)->f(2)->f(1)->f(0) 
          | 
    0 <- 1 <- 0 <- 1 <-+ 

提示:當我有這樣那樣的問題,我把的System.out.println()追溯碼,以瞭解流動。如果您使用的是Eclipse/Netbeans/Idea,則可以進入調試模式並進入代碼。

+0

BTW:這個函數打印參數的二進制值... –