Understanding the Order of Execution of Recursive Functions - c++

template <typename T>
T sum(stack<T>& s){
if (s.empty()){
return 0;
} else {
T first = s.top();
s.pop();
T total = sum(s)+first;
s.push(first);
return total;
}
}
The code above is designed to recursively sum the elements of any given stack of type T with the only condition being that the integrity of the stack must be restored at the end of the function. Meaning, I am allowed to make changes to the stack to sum the elements as long as it is in the same state as it was before it was passed when the function terminates.
As you will observe the given code works however I do not understand the control flow or execution sequence of the recursive calls and return statements. When I see this code I understand how the elements are summed, however I do not understand how the call to "s.push(first)" adds all of the elements back on to the stack. I'm having a hard time wrapping my head around why it wouldn't solely push the last element of the stack and then return the total.
My current understanding of why this works is incomplete and likely flawed and is as follows: because each return statement returns to the most recent caller, when the recursion hits the base case and terminates, the return statements will work their way back up the recursive call stack until it gets to the original caller and therefore executing "s.push()" at each movement back up the stack.
What is causing confusion for me is the execution sequence once the stack is empty and I think it is due to a lack of understanding the way the function recurses back up the call stack. If someone could lay out the execution sequence and explain the way recursion works with operations underneath the recursive call that would me much appreciated.
Thanks!

Your overall understanding is correct. You're only missing connecting the final dots.
The key point to remember is when a function returns, it returns to wherever it was called from. Recursive functions are no different in that fundamental respect. Recursive function calls work exactly the same way.
It will help to understand if you label each recursive call. Let's call the initial invocation of the recursive function "A". When the recursive function calls itself, recursively, call that invocation of the recursive function "B". Then it calls again, and that's "C". Followed by "D", and so on.
The key point to understand is that when a function returns, it returns to wherever it was called from. So, "D" returns to "C", which returns to "B", and it returns to "A".
Now look at your recursive function. When the stack had one value left, let's call it "D", it removes the "D" value from the stack and makes the recursive call "E", which discovers that the stack is empty.
So it returns to "D", which pushes the "D" value back to the stack, which now has one value again. Then it returns to "C", which pushes the "C" value back to the stack, which now has the two original, last, values on the stack, in the same order.
In this fashion, the function calls unwind in reverse order from their original calling sequence, restoring the stack to exactly what it was, originally.

Your function looks something like this:
if (s.empty()){
return 0;
} else {
T first = s.top();
s.pop();
T total = sum(s)+first;
s.push(first);
return total;
}
To kind of see how this works, let's pretend that this is actually a macro, and expand the function into what would generally get executed:
if (s.empty()){
return 0;
} else {
T first = s.top();
s.pop();
T total = if (s.empty()){
return 0;
} else {
T first = s.top();
s.pop();
T total = sum(s)+first;
s.push(first);
return total;
}+first;
s.push(first);
return total;
}
This is of course, just an example. Since it is not a macro,this isn't what really happens. It is just to illustrate.
However, the point is that the code in your function will get executed every time you call the function similarly to the second code snippet. Thus, what ends up happening is that the innermost function pushes to the stack, and then the calling function pushes to the stack, etc.. until everything gets pushed back on to the stack. So, even though there is one call to push on the stack, it will still get executed every time the function executes.

"If someone could lay out the execution sequence ... "
It is always allowed to add (removable) cout's to the executing code. The following illustrates one approach.
Note 1: To simplify, I removed template issues. The demo uses int.
Note 2: dumpStack is not recursive.
Note 3: m_stck is data attribute of the class, so it need not be passed from sumStack to sumStack.
#include <iostream>
using std::cout, std::endl; // c++17
#include <iomanip>
using std::setw, std::setfill;
#include <string>
using std::string, std::to_string;
#include <stack>
using std::stack;
#ifndef DTB_PCKLRT_HH
#include "../../bag/src/dtb_pclkrt.hh"
using DTB::PClk_t;
#endif
class StackW_t // stack wrapper UDT (user defined type)
{
private:
int m_N; // max elements
stack<int> m_stck; // default ctor creates an empty stack
public:
StackW_t(int N = 10) // simple default size
{
m_N = N; // capture
assert(m_N > 1); // check value
for (int i=0; i<m_N; ++i)
m_stck.push(N - i); // simple fill
}
~StackW_t() = default; // dtor default deletes each element of m_stck
// recurse level-vvvv
int sumStack(int rLvl = 1)
{
if (m_stck.empty())
{
cout << "\n" << setw(2*rLvl) << " " << setw(4) << "<empty>";
return 0;
}
else
{
int first = m_stck.top(); // top element
m_stck.pop(); // remove top element
cout << "\n" << setw(2*rLvl)
<< " " << setw(4) << first; // recurse report
// use first value then recurse into smaller stack with next rLvl
int sum = first + sumStack(rLvl+1);
cout << "\n" << setw(2*rLvl) // decurse report
<< " " << setw(3) << "(" << first << ")";
m_stck.push(first); // restore element after use
return sum;
}
}
void dumpStack(string lbl, int rLvl = 1)
{
stack<int> l_stck = m_stck; // for simplicity, use copy of
cout << "\n dumpStack " << lbl << setw(2*rLvl);
while (!l_stck.empty())
{
cout << " " << " " << l_stck.top();
l_stck.pop(); // remove displayed member
}
cout << "\n";
}
}; // class StackW_t
// Functor 829
class F829_t // use compiler provided defaults for ctor and dtor
{
PClk_t pclk; // posix clock access
public:
int operator()(int argc, char* argv[]) { return exec(argc, argv); }
private:
int exec(int , char** )
{
int retVal = 0;
// create, auto fill with value 1..10
StackW_t stk;
stk.dumpStack("before"); // invoke display
cout << "\n stk.sumStack(): ";
uint64_t start_us = pclk.us();
// invoke recursive compute, start at default rLvl 1
int sum = stk.sumStack();
auto duration_us = pclk.us() - start_us;
cout << "\n sum: " << sum << endl;
stk.dumpStack("after"); // invoke display
cout << "\n F829_t::exec() duration "
<< duration_us << " us (" << __cplusplus << ")" << std::endl;
return retVal;
}
}; // class F829_t
int main(int argc, char* argv[]) { return F829_t()(argc, argv); }
Note 4: during recurse, rLvl increases, so the value shifts to the right for each line
Note 5: during decurse, rLvl is restored upon function return, thus output is also restored to alignment
Note 6: before and after of stack shows successful restore of stack
Output:
dumpStack before 1 2 3 4 5 6 7 8 9 10
stk.sumStack():
1
2
3
4
5
6
7
8
9
10
<empty>
(10)
(9)
(8)
(7)
(6)
(5)
(4)
(3)
(2)
(1)
sum: 55
dumpStack after 1 2 3 4 5 6 7 8 9 10

Related

using ostream as function argument

I have a basic problem with understanding what ostream is exactly. I know that it's a base class for the output stream, but I can't quite gasp when to use it and why to use it instead of just saying std::cout.
So here I have this example where I have to create a new class named stack with a pop() function (just as in the class already provided by C++).
Here list_node is a struct which consists of two elements: the key (which is an integer) and an interator which points to the next integer.
Definition of list_node (already given):
struct list_node {
int key;
list_node∗ next;
// constructor
list_node (int k, list_node∗ n)
: key (k), next (n) {}
};
and here is the definition of the class (already given as well):
class stack {
public:
void push (int value) {...}
...
private:
list_node∗ top_node;
};
and here's the part with which I'm having trouble with:
void print (std::ostream& o) const
{
const list_node* p = top_node;
while (p != 0) {
o << p->key << " "; // 1 5 6
p = p->next;
}
}
I don't understand why they are using ostream& o as function argument. Couldn't they've just taken the top_node as argument and used as well .next function on it (.next reads the next list_node) and then they could've just printed it with the std::cout function. Why is it better to do it the way they did?
Why is it better to do it the way they did?
I am not sure of your question, and not sure it is a better way.
Perhaps the intent was for flexibility. Here is an example from my app library:
When I declare a data attribute as an ostream
class T431_t
{
// ...
std::ostream* m_so;
// ...
I can trivially use that attribute to deliver a report to 'where-m_so-points'. In this app, there are several examples of *mso << ... being used. Here is the primary example.
inline void reportProgress()
{
// ...
*m_so << " m_blk = " << m_blk
<< " m_N = 0x" << std::setfill('0') << std::hex << std::setw(16) << m_N
<< " " << std::dec << std::setfill(' ') << std::setw(3) << durationSec
<< "." << std::dec << std::setfill('0') << std::setw(3) << durationMSec
<< " sec (" << std::dec << std::setfill(' ') << std::setw(14)
<< digiComma(m_N) << ")" << std::endl;
// ...
}
Note that in the class constructor (ctor), there is a default assignment for m_so to std::cout.
T431_t(uint64_t maxDuration = MaxSingleCoreMS) :
// ..
m_so (&std::cout), // ctor init - default
// ..
{
// ...
When the user selects the dual-thread processing option, which is a command line option to perform the app in about 1/2 the time by using both processors of my desktop, the reports can become hard to read if I allow the two independent output streams to intertwine (on the user screen). Thus, in the object instance being run by thread 2, m_so is set some something different.
The following data attribute captures and holds thread 2 output for later streaming to std::cout.
std::stringstream m_ssMagic; // dual threads use separate out streams
Thread 2 is launched and the thread sets it's private m_so:
void exec2b () // thread 2 entry
{
m_now = Clock_t::now();
m_so = &m_ssMagic; // m_so points to m_ssMagic
// ...
m_ssMagic << " execDuration = " << m_ssDuration.str()
<< " (b) " << std::endl;
} // exec2b (void)
While thread 1 uses std::cout, and thread 2 uses m_ssMagic, 'main' (thread 0) simply waits for the joins.
The join's coordinate the thread completion, typically about the same time. Main (thread 0) then cout's the m_ssMagic contents.
//...
// main thread context:
case 2: // one parameter: 2 threads each runs 1/2 of tests
{ // use two new instances
T431_t t431a(MaxDualCoreMS); // lower test sequence
T431_t t431b(MaxDualCoreMS); // upper test sequence
// 2 additional threads started here
std::thread tA (&T431_t::exec2a, &t431a);
std::thread tB (&T431_t::exec2b, &t431b);
// 2 join's - thread main (0) waits for each to complete
tA.join();
tB.join();
// tA outputs directly to std::cout
// tB captured output to T431_t::m_ssMagic.
// both thread 1 and 2 have completed, so ok to:
std::cout << t431b.ssMagicShow() << std::endl;
retVal = 0;
} break;
To be complete, here is
std::string ssMagicShow() { return (m_ssMagic.str()); }
Summary
I wrote the single thread application first. After getting that working, I searched for a 'simple' way to make use of the second core on my desktop.
As part of my first refactor, I a) added "std::ostream m_so" initialized to &std::cout, and b) found all uses of std::cout. Most of these I simply replaced with "*m_so". I then c) confirmed that I had not broken the single thread solution. Quite easy, and worked the first try.
Subsequent effort implemented the command line 'dual-thread' option.
I think this approach will apply to my next desktop, when budget allows.
And from an OOP standpoint, this effort works because std::ostream is in the class hierarchy of both std::cout and std::stringstream. Thus
"std::cout is-a std::ostream",
and
"std::stringstream is-a std::ostream".
So m_so can point to instance of either derived class, and provide virtual method 'ostream-access' to either destination.

C++ // Not all control paths return a value

int bounce(int n) {
if (n == 0)
{
cout << "0" << endl;
}
if (n > 0)
{
cout << n << endl;
bounce(n - 1);
cout << n << endl;
}
}
int main()
{
int x;
cout << "Choose a number: ";
cin >> x;
cout << bounce(x) << endl;
system("pause");
return 0;
}
I recently started for my first time with C++ (2 hours ago or so :D ) and the problem i have is "Bounce: not all control paths return a value", I don't know how to fix this, obviously i need return 0; or something somewhere in the function but i can't find out where without ruining how it works.
Example : bounce(5) ==> prints out 5 4 3 2 1 0 1 2 3 4 5
TL DR: Where to place the return in bounce to make it work correctly.
Actually none of your control paths returns a value. As you only use the function to print something on the screen, it does not have to return anything. Just make the return type void:
void bounce(int n) {
/*...*/
}
And then dont cout the result of the function call (once you make it void the function wont return anything anyhow), i.e. instead of:
std::cout << bounce(x) << std::endl;
simply write
bounce(x);
You already print on the screen inside the function.
When you define a function in C++, you specify the return type before the function name.
Your int bounce() function is declared as returning an integer but it does not return any values at all. Therefore, that causes an error.
You can declare your function using void bounce(), which tells the compiler that your function will not return any values. That will eliminate the error.
Note: Although you use cout to display your values, this is different from returning a value in the way we are talking about. Returns values are specified using the return keyword.

return statement in Recursion: C++

I am trying to implement binary search tree and trying to implement searching the value from a node.
The book implements it through recursion.
To understand the procedure better, I am trying to apply the logic on an array.
Consider below code:
#include <iostream>
#include "BST.h"
using namespace std;
char Array[]={'A','B','C','D','E','F','G','H','I','J'};
char fn(int i,int x)
{
if( i == x)
{
cout << "Case : 1 " << endl;
return Array[x];
}
else if( i > x)
{
cout << "Case : 2 " << endl;
fn(--i,x);
}
else if(i < x)
{
cout << "Case : 3 " << endl;
fn(++i,x);
}
}
int main()
{
cout << fn(2,7) << endl ;
system("Pause");
return 0;
}
What I am trying to achieve is fn(int i,int x): from index i , search index x and return the value at index x.
The output is:
Case : 3
Case : 3
Case : 3
Case : 3
Case : 3
Case : 1
H
Press any key to continue . . .
The recursion logic works fine. But while compilation, it shows warning as main.cpp(28): warning C4715: 'fn' : not all control paths return a value
So if I modify my code as:
char fn(int i,int x)
{
if( i == x)
{
cout << "Case : 1 " << endl;
return Array[x];
}
else if( i > x)
{
cout << "Case : 2 " << endl;
return fn(--i,x);//added return here
}
else if(i < x)
{
cout << "Case : 3 " << endl;
return fn(++i,x);//added return here
}
}
There is no compilation warning and output is exactly the same. My question is what purpose does return in each 'else if test condition' serve, I am returning from my base condition i.e. return Array[x]; and this is what I wanted my function to return. Why to put return in all the test conditions?
EDIT
Just realized, second version of function still giving compilation warning main.cpp(30): warning C4715: 'fn' : not all control paths return a value
What should be done? How to resolve?
My question is what purpose does return in each 'else if case' serve, I am returning from my base condition i.e. return Array[x]; and this is what I wanted my function to return. Why to put return in all the test conditions?
This returns the value from the base case ultimately to the top level of the recursive calls.
To understand this better, remember that return simply gives execution back to the function which called fn(). When fn() is called recursively, the caller and callee are both copies of the fn() function. You may call fn() recursively many times and each recursive call must return the result to its parent and ultimately back to the function which originally called fn().
I suggest you get a piece of paper and a pencil and work manually through an example input. Trace each recursive call of fn() and what happens when you return from each of these. After you do this by hand, use a debugger to step through your code to check that it works the way that you expect.
Without the return before fn(--i, x), and fn(++i, x), the function does not return from those statements. It tries to run any other statements that function might have. However, there aren't any. It reaches the end of the function without encountering a return statement.
A function whose return type is not void must have a valid return statement. Otherwise, the behavior of the code is undefined. You can read more about that at https://stackoverflow.com/a/1610454/434551.
The compiler is helping you avoid that problem by reporting warnings.

Simulate std::vector with mixed const and non-const elements

I'd like to simulate a std::vector that has mixed const and non-const elements. More specifically, I want to have functions that operate on a vector and are allowed to see the entire vector but may only write to specific elements. The elements that can and cannot be written will be determined at runtime and may change during runtime.
One solution is to create a container that holds an array of elements and an equal sized array of booleans. All non-const access would be through a function that checks against the boolean array if the write is valid and throws an exception otherwise. This has the downside of adding a conditional to every write.
A second solution might be to have the same container but this time write access is done by passing an array editing function to a member function of the container. The container member function would let the array editing function go at the array and then check that it didn't write to the non-writable elements. This has the downside that the array editing function could be sneaky and pass around non-const pointers to the array elements, let the container function check that all is well, and then write to non-writable elements.
The last issue seems difficult to solve. It seems like offering direct writable access ever means we have to assume direct writable access always.
Are there better solutions?
EDIT: Ben's comment has a good point I should have addressed in the question: why not a vector of const and a vector of non-const?
The issue is that the scenario I have in mind is that we have elements that are conceptually part of one single array. Their placement in that array is meaningful. To use vectors of const and non-const requires mapping the single array that exist in concept to the two vectors that would implement it. Also, if the list of writable elements changes then the elements or pointers in the two vectors would need to be moved about.
I think you can accomplish what you wish with the following class, which is very simplified to illustrate the main concept.
template <typename T>
struct Container
{
void push_back(bool isconst, T const& item)
{
data.push_back(std::make_pair(isconst, item));
}
T& at(size_t index)
{
// Check whether the object at the index is const.
if ( data[index].first )
{
throw std::runtime_error("Trying to access a const-member");
}
return data[index].second;
}
T const& at(size_t index) const
{
return data[index].second;
}
T const& at(size_t index, int dummy) // Without dummy, can't differentiate
// between the two functions.
{
return data[index].second;
}
T const& at(size_t index, int dummy) const // Without dummy, can't differentiate
// between the two functions.
{
return data[index].second;
}
std::vector<std::pair<bool, T> > data;
};
Here's a test program and its output.
#include <stdio.h>
#include <iostream>
#include <utility>
#include <stdexcept>
#include <vector>
//--------------------------------
// Put the class definition here.
//--------------------------------
int main()
{
Container<int> c;
c.push_back(true, 10);
c.push_back(false, 20);
try
{
int value = c.at(0); // Show throw exception.
}
catch (...)
{
std::cout << "Expected to see this.\n";
}
int value = c.at(0, 1); // Should work.
std::cout << "Got c[0]: " << value << "\n";
value = c.at(1); // Should work.
std::cout << "Got c[1]: " << value << "\n";
value = c.at(1, 1); // Should work.
std::cout << "Got c[1]: " << value << "\n";
// Accessing the data through a const object.
// All functions should work since they are returning
// const&.
Container<int> const& cref = c;
value = cref.at(0); // Should work.
std::cout << "Got c[0]: " << value << "\n";
value = cref.at(0, 1); // Should work.
std::cout << "Got c[0]: " << value << "\n";
value = cref.at(1); // Should work.
std::cout << "Got c[1]: " << value << "\n";
value = cref.at(1, 1); // Should work.
std::cout << "Got c[1]: " << value << "\n";
// Changing values ... should only work for '1'
try
{
c.at(0) = 100; // Show throw exception.
}
catch (...)
{
std::cout << "Expected to see this.\n";
}
c.at(1) = 200; // Should work.
std::cout << "Got c[1]: " << c.at(1) << "\n";
}
Output from running the program:
Expected to see this.
Got c[0]: 10
Got c[1]: 20
Got c[1]: 20
Got c[0]: 10
Got c[0]: 10
Got c[1]: 20
Got c[1]: 20
Expected to see this.
Got c[1]: 200

Order of writing to a global variable from

In the program below I call a function foo() which sets a global variable i
and then calls the constructor of class A, where i should also be set, but
to 10. However the output of my program is 3 0, can you please explain?
#include <iostream>
int i;
class A
{
public:
~A()
{
i=10;
}
};
int foo()
{
i = 3;
A ob;
return i;
}
int main()
{
std::cout << "i = " << foo() << " " << i << "\n";
}
There are two important points to consider here:
The order of evaluation of arguments to a function is Unspecified. So either:
foo() gets executed first or
i gets printed first
It is specific to your compiler. Looks like your compiler evaluates argument from right to left, hence the global i which is 0 gets evaluated as 0. Remember that this order may be different for other compilers and you should not rely on behavior of one implementation.
As for why 3? The destructor for ob gets called after the function returns. So i gets set to 10 after the return, what gets returned is a copy and that copy has a value 3.
Its because return value gets copied after destructor.
I gets printed first and foo gets called later so the output 3 0.
If you print like below
cout << "i = " << i <<" " << foo()<< endl;
you will see 10 3 as output.
At the moment you are passing the 'i' as the argument, it's value is zero. The foo() will change the value in the destructor to 10 AFTER that.
As juanchopanza suggested, add another line std::cout << i; and you will see what you expect, because at that point the value is 10.
Print the foo() and i by using two cout statements as follows,
cout << "i of foo = " << foo();
cout <<"\ni in main = " << i << endl;
The output will be
i of foo = 3
i in main = 10
Earlier you were getting 3 0 as output because the overloaded operator << was being evaluated from left to right by your compiler.