c++recursion

Change recursive into iterative function


I got a recursive function for exporting information and I want to transform it into an iterative one for efficiency reasons (toy problem below). However, as there are statements in the recursive function after the call of the recursive function, I do not obtain a working iterative solution.

#include <iostream>
#include <stack>
using namespace std;

int n = 100;
int iMax = 2;

void fRecursive(int x)
{
    int u = 2 * x + 1;
    cout << u - 10 << ": ";

    if (u > n)
        return;

    for (int i = 0; i < iMax; ++i)
    {
        cout << u << "-" << i << "  "; 
        fRecursive(u);
        cout << "break" << endl;
    }
}

void fIterative(int x0)
{
    std::stack<int> myStack;
    myStack.push(x0);

    while (!myStack.empty())
    {
        int curx = myStack.top();
        myStack.pop();

        int u = 2 * curx + 1;
        cout << u - 10 << ": ";
        if (u > n)
            continue;

        for (int i = 0; i < iMax; ++i)
        {
            myStack.push(u);
            cout << u << "-" << i << "  ";

            cout << "break\n";
        }
    }
}

int main()
{
    int x0 = 10;

    cout << "Start Recursion" << endl;
    fRecursive(x0);
    cout << "End Recursion" << endl << endl;
    
    cout << "Start Iterative" << endl;
    fIterative(x0);
    cout << "End Iterative" << endl << endl;
    
    return 0;
}

I managed to change recursive to iterative functions when there is no code block after the call of the recursive function, but did not manage to do so when this function is there.


Solution

  • As a general solution you could mimic pushing the state on the stack. The relevant context you need includes also the value of i, so you could stack pairs of x and i. In some practical scenarios (like this toy example) you might find ways to do it without that additional element on the stack, but I believe for the more generic approach you'd want to have that i (or whatever you iterate with) stacked as well.

    Here is how that would look for your example:

    #include <tuple>
    
    void fIterative(int x) {
        std::stack<std::pair<int, int>> myStack;
    
        while (true) {
            int u = 2 * x + 1, i = 0;
            std::cout << u - 10 << ": ";
            myStack.push({u, 0});
            
            while (true) {
                std::tie(x, i) = myStack.top(); // or [x, i] = ... C++17
                myStack.pop();
                if (i < iMax && x <= n) {
                    break;
                }
                if (myStack.empty()) {
                    return;
                }
                std::cout << "break" << std::endl;
            }        
            std::cout << x << "-" << i << "  "; 
            myStack.push({x, i+1});
        }
    }