簡體   English   中英

難以理解連續的遞歸調用

[英]difficulty in understanding successive recursive calls

我試圖理解以下程序,其中存在連續的遞歸函數調用,但在跟蹤如何加載大頭針時感到困惑。

void func(char*);  // function prototype

int main(){
    func("123");
    return 0;
}

void func(char a[]){
    if(a[1]=='\0')
        return;
    func(a+1);
    func(a+1);
    printf("%c",a[1]);
}

輸出為 3 3 2

如果有人可以就此提出建議,將不勝感激...

這種多次遞歸調用是否以任何方式有益或在特定問題領域找到應用..?

只需將自己置於 CPU 的位置並逐行執行(或使用調試器來幫助完成該任務)。

第一個電話是

func("123")

此調用不滿足終止條件a[1] == '\\0' ,因此它調用

func("23");

對 func("23") 的調用依次調用

func("3")

滿足返回條件。 因此,該調用返回到前一個調用方 func("23")。

由於這些行,func("23") 繼續對 func("3") 進行另一個調用

func(a+1);
func(a+1);

在你的腦海中繼續這個執行程序的過程,並寫下每次調用printf會發生什么。 這將解釋您的輸出。

更新

請注意,對 printf() 的調用發生遞歸調用之后,例如調用

功能(“123”)

會像

  • 輸入 func("123")
  • 不滿足終止條件
  • 調用 func("23")
  • 再次調用 func("23")
  • printf("3")(這是一個[1])
  • 返回

發布的代碼是一個設計相當糟糕的遞歸實例。

以下代碼具有正確的遞歸“尾部”形式。

通過將反轉的字符串傳回 main 並讓 main 打印它,它可以做得更好。

它顛倒了 main() 傳遞給 func() 的字符串的順序

請在詢問運行時問題時,發布編譯代碼,包括頭文件所需的 #includes,這樣我們就不會猜測要包含哪些頭文件

#include <stdio.h>

void func(char*);  // function prototype

int main(){
    func("123");
    return 0;
}

void func(char a[])
{
    if(a[1]=='\0')   // check for end of recursive sequence
    {
        printf( "%c", a[0] ); // last tail action
        return;
    }

    func(a+1);    // step+next recursion
    printf( "%c", a[0] ); // tail action
    return;
}

使用斷點調試是理解遞歸的一種方式。 另一種方法是繪制遞歸調用樹。

遞歸調用樹

從圖中可以看出,在level0之后的每一層中,由於這兩行代碼,printf語句出現在每兩個節點之后:

func(a+1);
func(a+1);

一般來說,對於任何長度大於 0 的輸入字符串,這都會變成一個完美的二叉樹。 節點總數由以下公式給出:

2^(k+1) - 1 // k is the depth; here k = 2

執行的printf語句總數可以通過這個公式得到:

2^k - 1 // For k=2, there will be 3 printf statements each printing 3,3,2 respectively

遞歸可以簡單理解如下。

例如:

Func(int a){
    while(a>1)
        return a * func(a-1);
}

假設a = 5

發生的情況是它返回5 * func(4)

現在func(4)返回4 * func(3)並且它繼續這樣。

查看此示例以了解在斐波那契數列中使用遞歸

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM