这句话的意思是什么?需要更多的上下文信息才能正确翻译。

3
在这个程序中,如果用户输入数字3,输出将是 3 2 1 1 2 3,我理解了3 2 1的生成过程,但我不明白1 2 3是怎么产生的。
class GFG{ 
static void printFun(int test) 
{ 
    if (test < 1) 
        return; 
    else
    { 
        System.out.printf("%d ",test); 
        printFun(test-1); // statement 2 
        System.out.printf("%d ",test); 
        return; 
    } 
} 

public static void main(String[] args) 
{ 
    int test = 3; 
    printFun(test); 
} 
}

2
看看你的第二个 System.out.printf。顺便说一下,这种编程语言叫做 Java,而不是 JAVA - tkausl
1
从我看到的情况来看,它应该打印出 3 2 1 1 2 3,而不是 1 2 3 3 2 1,请您检查一下? - isstiaung
1
这是对同一函数的递归调用。它使用2而不是3再次调用该函数。 - isstiaung
1
第一条语句打印出“3 2 1”,第二条语句打印出“1 2 3”。它们的工作方式完全相同。一个打印“进入递归的路上”,一个打印“回到递归的路上”。最好在纸上逐步写下调用序列,或使用调试器逐行执行。 - Thilo
函数调用由栈维护。递归调用上方的语句是PUSH操作,递归调用下方的语句是POP操作。 - nits.kk
显示剩余2条评论
5个回答

4

追踪递归函数的一种方法是展开每个递归调用,就像数学表达式一样。

首先我们从下面开始:

printFun(3)

这将扩展为:

print(3) // I have shortened System.out.printf here to just "print" to remove the noise
printFun(2)
print(3)

我们仍有一个递归调用(printFun(2)),所以让我们展开它。

print(3)
print(2)
printFun(1)
print(2)
print(3)

继续扩展:

print(3)
print(2)
print(1)
printFun(0)
print(1)
print(2)
print(3)

最后一次(因为printFun(0)不执行任何操作,我们将其删除):

print(3)
print(2)
print(1)
print(1)
print(2)
print(3)

哦,看这里!这将产生输出结果为3 2 1 1 2 3


3

好的,递归的本质是将函数调用放在栈中,该栈从下往上构建。每当从堆栈中召回成员时,它应该从顶部开始获取,直到再次到达底部。我们一行一行地看:

第一次使用3调用函数

函数写入:3,并使用2调用自身 - 函数停止执行(语句2之后)并等待执行

函数写入:2,并使用1调用自身 - 函数停止执行并等待执行

函数写入:1,并使用0调用自身 - 由于值为0,调用立即返回。时间减少调用方堆栈并继续暂停的函数。

最后一个暂停的函数被重新激活(它是1),然后写入:1 - 然后函数返回

最后一个暂停的函数被重新激活(它是2),然后写入:2 - 然后函数返回

最后一个暂停的函数被重新激活(它是3),然后写入:3 - 然后函数返回

程序停止。

因此,您获得了您编写的数字行。


3

递归调用 printFun(test-1) 使得该方法按照以下方式继续调用:

printFun(3); // original
printFun(2);
printFun(1);
printFun(0);

到达此时,由于遇到了 printFun(0) 的条件,不会执行任何其他递归调用。
当前调用即最后一个递归调用(printFun(0))继续执行 return。然后执行回到调用者 printFun(1),它执行第二个 System.out.printf("%d ",test); 语句并返回。
同样的逻辑:运行控制流程一直上升到调用该方法的方法,即printFun(2)
这样一直上升,直到初始调用。
您可以按以下方式查看调用:
printFun(3)
   printFun(2)
      printFun(1)
          printFun(0)
                   -- No more recursive call, execution goes on where we are
          printFun(0)
      printFun(1)
   printFun(2)
printFun(3)

2
最初的回答:

我添加了一些打印命令来帮助你理解这个。

class GFG{
    static int count = 1;  
    static String combined = "";
    static void printFun(int test){ 
        System.out.println("No of times Function printFun has been called : " + count);
        count = count + 1;
        if (test < 1)
            return;
        else{
            System.out.println("Adding " + test + " to combined string");
            combined = combined + test;
            printFun(test-1); // statement 2 
            System.out.println("Returning to the previous call of printFun");
            combined = combined + test;
            System.out.println("Adding " + test  + " to combined string");
            return;
       }
    } 
    public static void main(String[] args){ 
        int test = 3;
        printFun(test);
        System.out.println(combined);
    }
}

我在最后打印出合并的字符串,打印语句应该显示函数如何被递归调用。"最初的回答"

0

函数调用由堆栈维护。函数的所有本地变量对应于函数调用实例。每个函数调用实例都在堆栈中维护。

递归调用之前的语句是PUSH操作,递归调用之后是POP操作。

因此,它是 (递归调用之前的语句)

print(3) PUSH(3), print(2) PUSH(2), print(1) PUSH(1)

接着是 (递归调用之后的语句)。

POP(1) print(1), POP(2) print(2), POP(3) print(3)

因此输出为3 2 1 1 2 3。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接