《C++语言程序设计基础》通过调试理解递归具体使用栈的方式

递归是指问题的求解有通式,像斐波拉契数列,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
       


总结来说递归是有很多栈的,函数堆栈是的,返回结果的存放和计算也是需要栈的,以及递归的实现用的也是栈,所以反过来想,用栈也是可以实现递归的。

猜你喜欢

转载自blog.csdn.net/shiheyingzhe/article/details/82765175