1) Вам нужно использовать стек, когда есть значения для сохранения для каждого вызова. В вашем случае вы не используете значения из более глубоких рекурсивных вызовов после рекурсивного вызова, поэтому в стеке нечего сохранять.
2) Это хвостовая рекурсия, если вызов самому себе является последним, что он делает. В комментариях @leppie вы выполняете 2*
после последнего вызова метода.
3) Общий подход заключается в использовании стека; однако в этом случае в стеке нечего сохранять, поэтому вы можете удалить его.
Вот несколько примеров, один из которых требует стека, а другой использует хвостовую рекурсию и не использует.
void reverseCounting(int i, int n) {
if (i >= n) return;
reverseCounting(i + 1, n);
cout << i << endl;
}
void counting(int i, int n) {
if (i >= n) return;
cout << i << endl;
counting(i + 1, n);
}
// you could just count backwards, but this is a simple example.
void reverseCountingLoop(int i, int n) {
// for C you can write you own stack to do the same thing.
stack<int> stack;
//// if (i >= n) return;
while (!(i >= n)) {
//// reverseCounting(i + 1, n);
// save i for later
stack.push(i);
// reuse i
i = i + 1;
}
// unwind the stack.
while (!stack.empty()) {
//// cout << i << endl;
i = stack.top(); stack.pop();
cout << i << endl;
}
}
void countingLoop(int i, int n) {
//// if (i >= n) return;
while (!(i >= n)) {
//// cout << i << endl;
cout << i << endl;
//// counting(i + 1, n);
// reuse i
i = i + 1;
}
//// nothing after the recursive call.
}