一、实验目的和要求
目的:熟悉递归的深层逻辑并动手实现
要求:同实验01
二、实验环境
编译器:Vscode +DevC++
系统:Windows10
CPU:i5-8265U@1.60GHz
三、实验内容
(1)用递归代码实现n!求解。
(2)利用转换规则(不简化) 将代码(1)转换为非递归代码。
(3)简化并梳理代码(2)的流程。
(4)用以上三个独立模块,测试6!的计算结果。
四、实验过程
4.1 任务定义和问题分析
需要实现三种代码格式
- 常规递归
- 底层递归模拟
- 简化(递归转非递归)
在使用递归算法时实际上是十分危险的,它的模型十分简单,但在数据规模超级大的时候就不能适用,容易造成爆栈,这也是为什么最终目标是将递归算法改成非递归算法。
4.2 数据结构的选择和概要设计
将三种代码实现方式分别包装成三个函数
- Recursive_f
- Goto_f
- Simple_f
主函数中使用
cout<<"Recursive_f:"<<Recursive_f(6)<<"\n";
cout << "goto_f:" << goto_f(6) << "\n";
cout << "simple_f:" << simple_f(6) << "\n";
进行数据的测试输出
-
- 详细设计
- Recursive_f
纯递归代码十分好写:
确定递归边界是n<=1时返回1
逐层都是累乘返回n*fun(n-1)
两行的事;
使用三目运算符的话 一行解决
- Goto_f
<并没有寻找到将标号入栈的实际操作,所以下面流程进行了一些小修改>
首先得建栈 stack<int>sta;
之后就是设置goto位置L1:
If判断
如果符合n>1的话就进行一系列操作:
入栈并递减:sta.push(n--)
返回第一个操作节点goto L1;
如果不符合n>1的话 不进行操作
设置goto位置L2:
If判断
如果栈内还有未处理的:
返回栈顶元素,并累乘ans*=sta.top(),sta.pop();
返回第二个操作节点goto L2;
跳出判断后就返回ans就可以
记得ans初始化为1
- Simple_f
Goto_f的流程可以简化为下面这个样子
(条件+技术有限 流程图用思维导图代替)
五、测试及结果分析
5.1 实验数据
6!
预计输出结果为
Recursive_f:720
goto_f:720
simple_f:720
5.2 结果及分析
达到预期
六、实验收获
略微掌握了goto的基本用法
对递归的内部运行有了了解
在写完纯递归代码时 其实我的simple_f代码就已经有眉目了 这不能说是我的能力,(之前遇到过)只是一种直觉—大概是这样的,为什么是这样我也不清楚,其实也就是经验主义—碰运气呗
对于中间的goto_f代码却是无从下手
在经过这次实践后,相信能够有套路地去解决这方面的问题了
七、参考文献
https://ask.csdn.net/questions/755200
参考了上面网站的goto使用格式以完成第一非递归代码
八、附录(源代码)
#include <cstdio>
#include <stack>
#include <iostream>
#include<cmath>
using namespace std;
stack<int>sta;
int Recursive_f(int n)
{
if(n==1)
return 1;
return n * Recursive_f(n - 1);
}
int goto_f(int n)
{
int ans = 1;
L1:
if(n>=1)
{
sta.push(n--);
goto L1;
}
L2:
if(!sta.empty())
{
ans *= sta.top();
sta.pop();
goto L2;
}
return ans;
}
int simple_f(int n)
{
int ans = 1;
while(n!=1)
ans *= n--;
return ans;
}
int main()
{
cout<<"Recursive_f:"<<Recursive_f(6)<<"\n";
cout << "goto_f:" << goto_f(6) << "\n";
cout << "simple_f:" << simple_f(6) << "\n";
int n;
cin >> n;
cout << "Recursive_f("<<n<<"):" << Recursive_f(n) << "\n";
cout << "goto_f(" << n << "):" << goto_f(n) << "\n";
cout << "simple_f(" << n << "):" << simple_f(n) << "\n";
system("pause");
return 0;
}