2012-12-15 52 views
2
#include <stdio.h> 

void call(int n) 
{ 
    if (n > 0) 
    { 
     call(--n) ; 
     printf("\n%d",n) ; 
     call(--n) ; 
    } 
} 

int main(void) 
{ 
    int a = 3 ; 
    call(a) ; 
    return 0 ; 
} 

在上面提到的代碼中,我很難理解它背後的邏輯。 我得到0 1 2 0作爲輸出。爲什麼?需要遞歸功能的解決方案

+3

使用調試器找出來,所以用'GCC -Wall -g -o prog.c中binprog',然後'GDB binprog'編譯並使用'gdb'的'bt'命令來逐步運行(''gdb''''''),以獲得回溯。解釋遞歸很困難,你需要了解它。 –

+0

該輸出正確。正如Basile所建議的那樣,通過調試器運行它來了解流程。 – anishsane

回答

5
call(3) 
│ n3=3 
│ --n3 (n3=2) 
├╴call(2) 
│ │ n2=2 
│ │ --n2 (n2=1) 
│ ├╴call(1) 
│ │ │ n1=1 
│ │ │ --n1 (n1=0) 
│ │ ├╴call(0) 
│ │ │ └ return 
│ │ │ 
│ │ │ printf("\n0");   ⇦ 0 
│ │ │ 
│ │ │ --n1 (n1=-1) 
│ │ ├╴call(-1) 
│ │ │ └ return 
│ │ └ return 
│ │ 
│ │ printf("\n1")    ⇦ 1 
│ │ 
│ │ --n2 (n2=0) 
│ ├╴call(0) 
│ │ └ return 
│ └ return 
│ 
│ printf("\n2");    ⇦ 2 
│ 
│ --n3 (n3=1) 
├╴call(1) 
│ │ n1=1 
│ │ --n1 (n2=0) 
│ ├╴call(0) 
│ │ └ return 
│ │ 
│ │ printf("\n0");    ⇦ 0 
│ │ 
│ │ --n1 (n1=-1) 
│ ├╴call(-1) 
│ │ └ return 
│ └ return 
└ return 
+0

+1給你..如何繪製這棵樹? –

+1

@GrijeshChauhan我從http://en.wikipedia.org/wiki/Box-drawing_character複製了字符。 –

+0

它是解釋的最佳方式。 –

5

首先,找到您的基本情況:call(n), when n<=0什麼都不做,只是返回。

在爲code(n)的定義說,一般情況下:「遞減n和遞歸(一路下跌);時再控制回來,打印n(其值保留),減量化,再遞歸」。

或者,用公式:

call(n) | when(n<=0) = NO-OP 
call(n) | otherwise = call(n-1), print(n-1), call(n-2) 

所以,

call(1) = call(0), print(0), call(-1) 
     = print(0) 

call(2) = call(1), print(1), call(0) 
     = print(0), print(1) 

call(3) = call(2), print(2), call(1) 
     = (print(0), print(1)), print(2), print(0) 

繼續,

call(4) = 0120+3+01 
call(5) = 0120301+4+0120 
call(6) = 012030140120+5+0120301 
.... 

我們似乎可以產生輸出結果的不確定序列,維護只是最多的兩個最近的值:

(n,a,b) --> (n+1,b,b+n+a) 

所以不是遞歸下來,對基本情況,這說明corecursion從開始的情況下高達而去,(2,0,1)(該1案件是由一個特殊的事實(1,_,0)覆蓋)。我們可以將它編碼爲一個實際上無限增長的序列(即「無限」)序列,或者我們可以將它製成一個無限循環。

這種非終止計算的目的是什麼?至描述的計算結果,一般。但是,當我們達到n的目標值時,切斷這種計算當然是非常容易的。

好處?而不是遞歸,我們得到一個迭代循環!

output(1) = "0" 
output(n) | when(n>1) = 
    let {i = 2, a="0", b="1"} 
    while(i<n): 
     i,a,b = (i+1),b,(b+"i"+a) 
    return b 
1

當試圖理解的代碼流對我用一個簡單的策略,我不能完成我的頭:

日誌中詳細的方式輸出。例如,您可以在應用程序的流程中映射您的調用函數,而不是使用簡單的printf語句。這裏有一個例子

#include <stdio.h> 

void call(int n, int depth) 
{ 
    printf("%.*s(enter) n is (%d)\n", ++depth, "-----", n); 
    if (n > 0) 
    { 
     call(--n, depth) ; 

     call(--n, depth) ; 
    } 
    printf("%.*s(exit) n is (%d)\n", depth--, "-----", n); 
} 

int main(void) 
{ 

    int a = 3 ; 

    call(a, 0) ; 
    getchar(); 
    return 0 ; 
} 

這將導致:

-(enter) n is (3) 
--(enter) n is (2) 
---(enter) n is (1) 
----(enter) n is (0) 
----(exit) n is (0) 
----(enter) n is (-1) 
----(exit) n is (-1) 
---(exit) n is (-1) 
---(enter) n is (0) 
---(exit) n is (0) 
--(exit) n is (0) 
--(enter) n is (1) 
---(enter) n is (0) 
---(exit) n is (0) 
---(enter) n is (-1) 
---(exit) n is (-1) 
--(exit) n is (-1) 
-(exit) n is (1)