递归算法实际上是一种分而治之的方法,它把复杂问题分解为简单问题来求解。对于某些复杂问题(例如
hanio塔问题),递归算法是一种自然且合乎逻辑的解决问题的方式,但是递归算法的执行效率通常比较差。因此
,在求解某些问题时,常采用递归算法来分析问题,用非递归算法来求解问题;另外,有些程序设计语言不支持
递归,这就需要把递归算法转换为非递归算法。
将递归算法转换为非递归算法有两种方法,一种是直接求值,不需要回溯;另一种是不能直接求值,需要回溯。
前者使用一些变量保存中间结果,称为直接转换法;后者使用栈保存中间结果,称为间接转换法,下面分别讨论
这两种方法。
1. 直接转换法
直接转换法通常用来消除尾递归和单向递归,将递归结构用循环结构来替代。
尾递归是指在递归算法中,递归调用语句只有一个,而且是处在算法的最后。例如求阶乘的递归算法:
long fact(int n)
{
if (n==0) return 1;
else return n*fact(n-1);
}
当递归调用返回时,是返回到上一层递归调用的下一条语句,而这个返回位置正好是算法的结束处,所以
,不必利用栈来保存返回信息。对于尾递归形式的递归算法,可以利用循环结构来替代。例如求阶乘的递归算法
可以写成如下循环结构的非递归算法:
long fact(int n)
{
int s=0;
for (int i=1; i
s=s*i; //用s保存中间结果
return s;
}
单向递归是指递归算法中虽然有多处递归调用语句,但各递归调用语句的参数之间没有关系,并且这些递归
调用语句都处在递归算法的最后。显然,尾递归是单向递归的特例。例如求斐波那契数列的递归算法如下:
int f(int n)
{
page: 2
The Home of jetmambo - 递归算法转换为非递归算法
if (n= =1 | | n= =0) return 1;
else return f(n-1)+f(n-2);
}
对于单向递归,可以设置一些变量保存中间结构,将递归结构用循环结构来替代。例如求斐波那契数列的算
法中用s1和s2保存中间的计算结果,非递归函数如下:
int f(int n)
{
int i, s;
int s1=1, s2=1;
for (i=3; i {
s=s1+s2;
s2=s1; // 保存f(n-2)的值
s1=s; //保存f(n-1)的值
}
return s;
}
2. 间接转换法
该方法使用栈保存中间结果,一般需根据递归函数在执行过程中栈的变化得到。其一般过程如下:
将初始状态s0进栈
while (栈不为空)
{
退栈,将栈顶元素赋给s;
if (s是要找的结果) 返回;
else {
寻找到s的相关状态s1;
将s1进栈
}
}
间接转换法在数据结构中有较多实例,如二叉树遍历算法的非递归实现、图的深度优先遍历算法的非递归实
现等等,请读者参考主教材中相关内容。
原作者不详
分享到:
相关推荐
可以使用递归算法或动态规划算法来解决该问题。 2. 找出数组中t的位置 该题目考察了候选人的算法设计能力和编程能力。可以使用二分查找算法或哈希表来解决该问题。 3. 布丰投针问题 布丰投针问题是一道经典的...
7. **组合和排列生成**:在组合学中,组合和排列问题可以通过递归或回溯算法来解决,如鸽巢原理的应用。 8. **模逆运算**:在模运算中,找到一个数的逆元对于加密算法(如RSA)和某些数学问题至关重要。欧几里得...
这些算法在C语言中都有相应的实现,便于理解和应用。 1. **拉格朗日插值多项式**: 拉格朗日插值是一种用于通过一系列离散点构建连续函数的方法。给定n个点对{(x0, y0), (x1, y1), ..., (xn-1, yn-1)},拉格朗日...
5. **差分(Difference Array)**:差分操作常用于数组的修改和查询,文件中的一维差分更新和二维差分更新类似前缀和,但涉及增加和减少操作。 6. **位操作**:如`x &= (x - 1)`,这个操作会移除`x`的最右边的一个1...
常见的自适应滤波算法有LMS(最小均方误差)算法和RLS(递归最小二乘)算法。 在TDOA(Time Difference of Arrival)系统中,通过比较不同接收器接收到同一信号的时间,可以确定信号源的位置。通常,至少需要三个...
- **割顶和块的算法**:割顶和块的概念用于分析图的连通性和结构特性。割顶是指移除它会导致图不连通的顶点;而块是指一个连通的子图,移除任何顶点都不会使它变得不连通。 #### 计算几何算法 计算几何是一门研究...
在"erfenfa.txt"文件中,可能包含了对二分法查找的详细实现、优化策略,比如迭代和递归两种常见实现方式,以及如何处理等于中间元素的情况,这些都会帮助我们更好地理解和应用二分法查找算法。 在实际编程中,...
在编程领域,掌握数据结构和算法是至关重要的。Python作为一种流行的高级编程语言,因其简洁易懂的语法特性,成为初学者学习数据结构和算法的首选工具。本教程将深入探讨Python中的各种数据结构和算法,帮助你提升...
通过针对不同复杂度的视频图像应用简化版的四叉树进行测试,测试结果表明,与传统的四叉树递归算法相比,该算法在不降低编码质量的前提下,平均编码复杂度降低了14QP%。QP是量化参数(Quantization Parameter),在...
5. **递归**:递归算法在解决数学问题(如阶乘、斐波那契数列)时非常有用。 ```csharp int factorial(int n) { if (n == 0) return 1; return n * factorial(n - 1); } ``` 6. **排序算法**:C#中可以实现多种...
matlab中存档算法代码ReBEL:递归贝叶斯估计库 用于递归贝叶斯估计的Matlab工具包 俄勒冈健康与科学大学2006版权所有 1)什么是叛逆? ReBEL是功能和脚本的Matlab:registered:工具箱,旨在促进一般状态空间模型中的...
根据给定的文件标题、描述和部分内容,我们可以总结出三个主要的算法知识点,这些算法均用C语言实现。下面将详细解析每个算法的功能、应用场景以及其实现原理。 ### 1. Lagrange 插值法 #### 算法概述: Lagrange...
其关键在于牛顿 Forward Divided Difference表格,通过递归地计算差商,构建出多项式的系数。例如,对于两个数据点,可以得到一次多项式;对于三个数据点,则构建二次多项式。牛顿插值法的优点在于计算过程相对简单...
这包括对非线性模型的线性化处理,以及如何在MATLAB环境中构建和执行EKF算法。 总结来说,TDOA_AOA定位的扩展卡尔曼滤波算法是一种有效的融合TDOA和AOA信息,进行高精度定位的方法。通过EKF的递归估计过程,它能够...
递归算法和链队列是两种不同的实现方式。递归算法通过遍历像素并将其邻居添加到处理列表中来填充,而链队列则使用先进先出(FIFO)的数据结构来存储待处理的像素。 2. **二次B样条曲线**:是一种光滑的曲线类型,...
- **Ο(2^n)**:指数时间复杂度,常见于递归算法或全排列等问题。 - **Ο(n!)**:阶乘时间复杂度,非常高的复杂度,通常出现在全排列等问题中。 #### 2. **示例解析** - **单层循环**:`for(let i = 0; i ; i++)...
- 非递归分治如非递归二叉树中序遍历,使用栈存储待访问节点,避免了递归调用,但依然遵循分治思想。 10. 归并排序 对于待排序序列(5, 3, 1, 9),归并排序的画图过程会涉及将序列拆分为更小的子序列,然后逐个...
### 字符串近似匹配算法概述 #### 一、应用背景及重要性 字符串近似匹配算法在多种应用场景中发挥着关键作用。例如,在字处理软件中的拼写检查功能能够帮助用户纠正输入错误,提高文档质量;在语音或文字识别系统...
- 算法及其运行时间(Algorithms and running times):这可能指的是分析算法的时间复杂度和空间复杂度,以及如何选择和改进算法以提高效率。 - 代换法(Substitution method):是一种证明递归关系的渐近界的方法,...
Newton插值公式可以表示为差分表的形式,或者用递归的Forward和Backward Divided Difference公式表示。 Forward Divided Difference(前向差分)定义为: \( [f, x_0, x_1, ..., x_n] = f[x_0, x_1, ..., x_n] ...