简单递归(递归函数中只有一条调用自己的语句)

简单递归

1.递归本质(为什么可以递归)

可以递归的原因:

函数的每一次调用,都会在函数栈开辟新的内存,所以递归的本质就是栈

2.尾递归

形式:

<返回值类型> f(形参列表){
    if(结束条件)
        return 返回值;
    /*
        ...
        ...
        操作
    */

    f(实参);
}

将操作放在递归调用之后另一种理解:先操作,再下一次压栈
举个例子:

void f(int x) {

    if (x == 0)
        return;

    cout << x << endl;//这里用输出代替操作

    f(x / 10);

    return;
}

例如,调用f(1234):1234压栈(压栈方向,向上,所以下面的图从最后一行开始向上看)

0 返回条件满足; 退栈
1 输出1; f(1/10):0压栈
12 输出12; f(12/10):1压栈
123 输出123; f(123/10):12压栈
1234 输出1234; f(1234/10):123压栈

过程:
开始->1234压栈,输出->123压栈,输出->12压栈,输出->1压栈,输出->0压栈,0退栈->1退栈->12退栈->123退栈->1234退栈->递归结束

总结:

尾递归操作顺序按照压栈顺序访问操作。

3.头递归

形式:

<返回值类型> f(形参列表){
    if(结束条件)
        return 返回值;

    f(实参);
    /*
        ...
        ...
        操作
    */
}

将操作放在递归调用之后另一种理解:先下一次压栈,再操作
举个例子:

void f(int x) {

    if (x == 0)
        return;

    f(x / 10);

    cout << x << endl;//这里用输出代替操作

    return;
}

例如,调用f(1234):1234压栈(压栈方向,向上,所以下面的图从最后一行开始向上看)

0 返回条件满足; 退栈
1 f(1/10):0压栈;
12 f(12/10):1压栈;
123 f(123/10):12压栈;
1234 f(1234/10):123压栈;

过程:
开始->1234压栈->123压栈->12压栈->1压栈->0压栈,0退栈->输出1->1退栈->输出12->12退栈->输出123->123退栈->输出1234->1234退栈->递归结束

总结:

尾递归操作顺序按照退栈顺序访问操作。

4.中间递归

形式:

<返回值类型> f(形参列表){
    if(结束条件)
        return 返回值;

    /*
        ...
        ...
        操作
    */

    f(实参);

    /*
        ...
        ...
        操作
    */
}

将操作放在递归调用之后另一种理解:操作,下一次压栈,再操作
举个例子:

void f(int x) {

    if (x == 0)
        return;

    cout << x << endl;//这里用输出代替操作   

    f(x / 10);

    cout << x << endl;//这里用输出代替操作

    return;
}

例如,调用f(1234):1234压栈(压栈方向,向上,所以下面的图从最后一行开始向上看)

0 返回条件满足; 退栈
1 f(1/10):0压栈;
12 f(12/10):1压栈;
123 f(123/10):12压栈;
1234 f(1234/10):123压栈;

过程:
开始->1234压栈,输出->123压栈,输出->12压栈,输出->1压栈,输出->0压栈,0退栈->输出1->1退栈->输出12->12退栈->输出123->123退栈->输出1234->1234退栈->递归结束

总结:

中间操作顺序先按照压栈顺顺序操作,再按照退栈顺序访问操作。

递归总结->简单递归可以用简单循环来代替

首先,先将带操作的数使用循环入栈

尾递归

按照入栈顺序使用循环访问 还可以再入栈的时候就进行访问,这样可以少一次循环

while(i = base; i <= top; ++i){
    /*
        ...
    */
}

头递归

按照退栈顺序使用循环访问

while(i = top; i > base ; --i){
    /*
        ...
    */
}

中间递归

循环两次

  1. 相当于尾递归,按照入栈顺序访问一次(可以入栈时访问,这个循环就可省略)
  2. 相当于头递归,按照退栈顺序再访问一次

    while(i = base; i <= top; ++i){
        /*
            ...
        */
    }
    
    while(i = top; i > base ; --i){
        /*
            ...递归调用后的操作
        */
    }
    

猜你喜欢

转载自blog.csdn.net/qq2071114140/article/details/88777881