如何理解java中递归的概念?

如何理解java中递归的概念?,java,recursion,concept,Java,Recursion,Concept,我是java编程新手,我们的老师教我们递归的概念,我发现它有点复杂。我只知道它的工作原理像一个循环(像4的阶乘),但我仍然不太明白它为什么会这样工作。我能得到关于这个话题的详细解释吗?这是我老师用来解释的代码和图片 package javaapplication1; public class JavaApplication1 { static int factorial(int n){ int t; if(n == 0){ return 1; } el

我是java编程新手,我们的老师教我们递归的概念,我发现它有点复杂。我只知道它的工作原理像一个循环(像4的阶乘),但我仍然不太明白它为什么会这样工作。我能得到关于这个话题的详细解释吗?这是我老师用来解释的代码和图片

package javaapplication1;

public class JavaApplication1 {

static int factorial(int n){
    int t;
    if(n == 0){
        return 1;
    } else {
        t = factorial(n - 1);
        return n * t;
    }
}
public static void main(String[] args) {
    System.out.println(factorial(5));
    }
}
在下图中,蓝色表示堆栈缠绕,绿色表示堆栈展开,我也不知道堆栈缠绕和展开是什么


当一个人知道一个任务可以分解成类似的小任务时,我们使用递归或调用相同的方法(直到我们满足某个条件)。
递归不仅有助于执行一个问题,而不必定义或调用另一个方法,它还有助于可视化执行任务的模式

当调用另一个方法时,会创建一个堆栈框架来保存当前方法的状态,并将其推送到堆栈上。这与调用自身或其他方法的方法无关

当调用返回时,堆栈帧将弹出堆栈,方法的状态将恢复,并在调用方法中继续执行

递归是指一个方法(直接或间接)调用自身。递归方法的一般形式为:

  • 如果参数满足终止条件,则返回(通常是结果)
  • 否则,为下一次迭代调整参数并调用self
你老师写的代码有一些风格问题。如果这样写会更清楚:

static int factorial(int n) {
    if (n == 0) {
        return 1;
    } 
    return n * factorial(n - 1);
}
消除不必要的变量
t
和冗余的
else
(当“if”返回时没有“else”-只有继续执行)

我会这样写,完全消除
if

static int factorial(int n) {
    return n == 0 ? 1 : n * factorial(n - 1);
}

我不确定它是否能解释,但如果你有一个precalculus类,那么你应该知道阶乘可以在两个waqy中定义

n=1*2*..*n

我们定义了什么

一!=一,

n=n*(n-1)

试着让自己明白这些定义是等价的。选择让我们说,5

根据第二个定义

五!=5*4!

但是4=4*3! 所以5=5*4*3!

但是第三=3*2! 所以5=5*4*3*2!

等等。继续做直到你达到1!。但是1=1所以你停下来

编程中的递归也是一样


就我个人而言,我不喜欢阶乘问题。我发现它很难理解,而且我认为它不能清楚地解释递归。让我们看一个不同的例子。假设我们要打印1-100之间的数字。这是一个非常简单的任务,带有for循环和计数器,但也可以通过递归完成。例如:

public static void main(String[] args) {
    numbersAscending(1);
    numbersDescending(1);   
}
//Prints 1 2 3 ... 100
public void numbersAscending(int x){
    System.out.println(x);
    if(x < 100){
        numbersAscending(x+1);
    }
}
//Prints 100 99 98 ... 1
public void numbersDescending(int x){
    if(x < 100){
        numbersDescending(x+1);
    }
    System.out.println(x);
}
publicstaticvoidmain(字符串[]args){
数字显示(1);
数字下降(1);
}
//打印1 2 3。。。100
公共无效号码搜索(int x){
系统输出println(x);
如果(x<100){
数字搜索(x+1);
}
}
//打印100 99 98。。。1.
公共作废编号递减(整数x){
如果(x<100){
数字递减(x+1);
}
系统输出println(x);
}
调用函数时,该调用位于堆栈顶部。把这想象成一堆卡片。每个都有一个数字(1-100)。当函数调用自身时,会向堆栈中添加一张新卡。当函数完成时,它将从堆栈中移除

因此,对于上面的示例,每次调用numbersAscending时,它都会在再次调用该函数之前打印出x的当前值。这将导致按1-100的顺序打印数字。一旦达到100,它就停止调用自己,并将每个函数从堆栈中弹出


另一方面,每次调用numbersDescending时,它都会在打印号码之前再次调用自己。这样,x直到达到100才开始打印。然后它沿着堆栈向下移动,在返回主方法时打印每个数字

递归函数是一个调用自身直到到达返回语句的函数,该语句阻止它调用自身。以你的例子,阶乘函数。 阶乘是一个数学函数,它返回与自身相乘的数字-1乘以自身-2。。。乘以1,例如:5的阶乘=5!=5x4x2x1=120。 它也等于自身乘以自身-1的阶乘,即:5!=5x4! 考虑到0!=1. 为了在Java代码中表示这一点,您需要一个循环,该循环将从1开始的数字相乘,直到计算其阶乘为止。 此外,在解释您的代码时,让我们计算阶乘(5): Factorial()返回一个整数

来自main()的初始调用:5!=0,然后跳过条件(n==0);T =阶乘(5-1)=阶乘(4)

Factorial的第二次调用(4):4!=0,然后跳过条件(n== 0); t=阶乘(4-1)=阶乘(3)

Factorial的第三次呼叫(3):3!=0,然后跳过条件(n== 0); t=阶乘(3-1)=阶乘(2)

Factorial的第四次呼叫(2):2!=0,然后跳过条件(n== 0); t=阶乘(2-1)=阶乘(1)

Factorial的第五次呼叫(1):1!=0,然后跳过条件(n== 0); t=阶乘(1-1)=阶乘(0)

来自阶乘(0)的第六个调用:0==0,然后返回值1

第一次返回,1,到第五次调用(阶乘(1)):返回n*t=返回1*1 =返回值1

第二次返回,1,到第四次调用(阶乘(2)):返回n*t=返回 2*1=返回值2

第三次返回,2,到第三次调用(阶乘(3)):返回n*t=返回3*2 =返回值6

第二次返回,6,到第二次调用(阶乘(4)):返回n*t=return 4*6=返回值24

第二次返回,24,到第一次调用(阶乘(5)):返回n*t=retu
/*This program in java will help you to understand all the basics of 
  recursion:
  ->how control flows in recursion
  ->how return is executed in the recursive functions
  ->how and when the statements after recursive function area executed.*/

public class Understanding_Rec{

public static int rec(int x)
{
    if(x<5)
    {
        System.out.println("-->Smaller than 5");
        rec(x+1);
        System.out.println("<--After recursion inside x<5");
        return x;
    }
    else if(x<7)
    {
        System.out.println("-->Smaller than 7");
        rec(x+1);
        System.out.println("<--After recursion inside x<7");
    }
    System.out.println("<--No Condition Statement");
    return x;
}

public static void main(String[] args)
{
    int x=1;
    rec(x);
    System.out.print(x+"Inside main");
}
}