递归是指问题的求解有通式,像斐波拉契数列,Fibonacci(n)=Fibonacci(n-1)+Fibonacci(n-2),递归求解问题时用到的结构就是栈,使用visual studio,可以找到递归求解的栈和返回值的栈,递归具体是怎么使用栈的。这里分为递归栈和返回结果栈。
先说明递归的结构,递归需要有通式,还要有相应的返回条件,如果没有返回条件会导致无法退出函数,所以返回条件是很重要的。
这里以Fibonacci数列和链表打印作为示例:
#include "pch.h"
#include <iostream>
using namespace std;
int fib(int n);
int main(){
int n, answer;
cout << "Enter number: ";
cin >> n;
cout << "\n\n";
answer = fib(n); //断点的位置
cout << answer << " is the " << n << "th Fibonacci number\n";
}
int fib(int n) {
cout << "Processing fib(" << n << ")...";
if (n <= 2) {
cout << "Return 1!\n";
return 1;
}
else {
cout<<"Call fib("<<n-2<<") and fib("<<n-1<<").\n";
return fib(n - 1) + fib(n - 2);
}
}
按F5键进入调试,输入值5:Enter number: 5,逐语句F11调试
第1次进入fib函数,n=5,5入栈,3、4分别入栈,递归栈为5 3 4,5是栈底元素,4是栈顶元素,接着对栈顶元素4进行递归
1层递归
第2次进入fib函数,n=4,2、3分别入栈
递归栈为5 3 4
4 2 3,3是第2层的栈顶元素,接着对栈顶元素3进行递归
2层递归
第3次进入fib函数,n=3,1、2分别入栈
递归栈为5 3 4
4 2 3
3 1 2,2是第3层的栈顶元素,接着对栈顶元素2进行递归
3层递归
第4次进入fib函数,n=2,fib函数返回1,有返回值,第3层的栈顶元素出栈,然后检查第3层栈是否只有一个元素,否,1是第3层栈顶元素,接着对栈顶元素1进行递归
递归栈为5 3 4
4 2 3
3 1 ,由于有返回结果,返回值入栈,返回结果栈为 1
3层递归
第5次进入fib函数,n=1,fib函数返回1,有返回值,第3层的栈顶元素出栈,然后检查第3层栈是否只有一个元素,是,pop出第3层元素3,并pop出第2层栈顶元素,pop的原因是Fibonacci(3)=Fibonacci(2)+Fibonacci(1),这层函数调用是有结果的,3的递归已经完成,需要pop掉。
递归栈为5 3 4
4 2 ,2是栈顶元素,接着第2层的栈顶元素2进行递归,由于有返回结果,返回值入栈,返回结果栈为 1 1,Fibonacci(2)=1,Fibonacci(1)=1,又因为这层函数递归两个返回值都有,可以计算第3层递归的返回值,所以栈中的后两个数相加,最终返回结果栈为2。
2层递归
第6次进入fib函数,n=2,fib函数返回1,有返回值,第2层的栈顶元素出栈,然后检查第2层栈是否只有一个元素,是,pop出第2层元素4,并pop出第1层栈顶元素,pop的原因是Fibonacci(4)=Fibonacci(2)+Fibonacci(3),这层函数调用是有结果的,4的递归已经完成,需要pop掉。
递归栈为5 3,3是栈顶元素,接着第1层的栈顶元素3进行递归,由于有返回结果,返回值入栈,返回结果栈为 2 1,Fibonacci(3)=2,Fibonacci(2)=1,又因为这层函数递归两个返回值都有,可以计算第2层递归的返回值,所以栈中的后两个数相加,最终返回结果栈为3。
1层递归
第7次进入fib函数,n=3,1、2分别入栈,
递归栈为5 3
3 1 2 , 第2层的栈顶元素是2,接着对栈顶元素2进行递归,返回结果栈为3。
2层递归
第8次进入fib函数,n=2,fib函数返回1,有返回值,第2层的栈顶元素出栈,然后检查第2层栈是否只有一个元素,否,1是第2层栈顶元素,接着对栈顶元素1进行递归
递归栈为5 3
3 1,由于有返回结果,返回值入栈,返回结果栈为 3 1
2层递归
第9次进入fib函数,n=1,fib函数返回1,有返回值,第2层的栈顶元素出栈,然后检查第2层栈是否只有一个元素,是,pop出第2层元素3,并pop出第1层栈顶元素,pop的原因是Fibonacci(3)=Fibonacci(2)+Fibonacci(1),这层函数调用是有结果的,3的递归已经完成,需要pop掉。
递归栈为5,由于有返回结果,返回值入栈,返回结果栈为 3 1 1,Fibonacci(2)=1,Fibonacci(1)=1,又因为这层函数递归两个返回值都有,可以计算第2层递归的返回值,所以栈中的后两个数相加,返回结果栈为3 2
由于递归已经完成,只有1层递归栈并且只有1个元素,所以返回结果栈中的后两个数相加得到3+2=5,返回值为5。
递归完成的
最终返回结果:
链表逆序打印: 链表值为A B C D E
void recursion(ListNodes* head){
if (head == NULL)
return;
if (head->m_Next != NULL){
recursion(head->m_Next);
}
cout << head->m_nValue << "\t";
}
同样F5进入调试,逐语句进行,由于没有return返回值,所以没有返回结果栈
调试过程中可以看到recursion函数是不断入栈的,最终打印结果就是函数依次出栈的结果E D C B A
总结来说递归是有很多栈的,函数堆栈是的,返回结果的存放和计算也是需要栈的,以及递归的实现用的也是栈,所以反过来想,用栈也是可以实现递归的。