C++中函数的递归

Recursion with functions in C++

本文关键字:递归 函数 C++      更新时间:2023-10-16

我在理解以下代码时遇到问题:

#include <iostream>
using namespace std;
void Print_numm(int numm){
    cout<<numm;
    if (numm<=4) {
        Print_numm(numm+1);
    }
    cout<<numm;
}

int main() {
    Print_numm(1);
    return 0;
}

输出为1234554321。我理解递归直到它打印出123455。但是,为什么编译器会将其余的数字打印为1呢?编译器是否每次都执行第二个"cout"?如果是这样的话,它是如何保持数字直到打印到5,然后向下打印其余的数字的?

如果您可视化调用的执行,它将更容易理解:

Print_numm(1)
-> cout 1
-> Print_numm(2)
--> cout 2
-->Print_numm(3)
---> cout 3
---> Print_numm(4)
----> cout 4
----> Print_numm(5)
-----> cout 5
-----> cout 5
----> cout 4
---> cout 3
--> cout 2
-> cout 1

您熟悉堆栈吗?

该函数调用自己,向上打印每个数字,然后从最后一次递归调用返回,向下遍历数字,重复从递归返回。它只执行递归调用后包含的其余代码。

这方面的一个简单表示是:

    print_numm(1):
    cout << 1
    print_numm(1+1):
        cout << 2
        print_numm(2+1):
            cout << 3
            print_numm(3+1):
                cout << 4
                print_numm(4+1):
                    cout << 5
//now the number is bigger than 4 so the function
//will return from recursion
                    cout << 5
//now the function is done,but the function that called print_numm(5) is waiting to finish
//so it executes the rest of the code printing 4,same with all waiting for print_numm(4) and so on
                cout << 4
            cout << 3
        cout << 2
    cout << 1

以下是代码的执行方式,您可以很容易地通过这种方式告诉您为什么会在讨论中得到输出:

Print_numm(1)->
    cout<<1
    Print_numm(2)->
        cout<<2
        Print_numm(3)->
            cout<<3
                Print_numm(4)->
                cout<<4
                    Print_num(5)->
                        cout<<5
                        cout<<5
                cout<<4
            cout<<3
        cout<<2
    cout<<1

第二个cout放在递归调用之后,这意味着它将在所有内部调用返回后执行。

您可以看到它会这样做(假设它返回)。

cout<<1;
Print_numm(2);
cout<<1;

可以扩展为:

cout<<1;
cout<<2;
Print_numm(3);
cout<<2;
cout<<1;

然后最终输出"1234554321"。

由于条件numm<4在numm=5时变为假。因此,numm停止递增,并停止执行先前调用函数的其余代码。

函数从1到5递归,这些数字在对cout << numm的第一次调用(Print_numm函数的第一行)中输出。一旦if语句求值为false,递归就开始展开,当对Print_numm的调用返回时,它们会遇到函数最后一行的最后一行cout << numm,并从5打印到1。

如果在代码中添加一些额外的诊断,执行会更容易可视化。考虑一下这个变化:

#include <iostream>
using namespace std;
void Print_numm(int numm){
    cout << "enter: " << numm << endl;
    if (numm<=4) {
        Print_numm(numm+1);
    }
    cout << "exit: " << numm << endl;
}

int main() {
    Print_numm(1);
    return 0;
}

哪个生产:

enter: 1
enter: 2
enter: 3
enter: 4
enter: 5
exit: 5
exit: 4
exit: 3
exit: 2
exit: 1

您也可以使用调试器来逐步完成,以帮助您更好地理解这一点。

一个重要的代码理解原则添加良好的诊断大大减少了理解正在发生的事情所需的脑力劳动和能力