首先我来谈一下递归的定义:递归过程一般通过函数或子过程来实现。递归方法:在函数或子过程的内部,直接或者间接地调用自己的算法。可以简单的表示成fun( r ) { fun( k ) }。当然这个递归是个死循环,永远不停的递归,所以对于递归,必须有一个出口,用来结束递归函数的调用,并返回结果,类似于循环结构的终止条件。所以递归和循环也可以是等价的。
下面我们来讨论一下递归的优缺点:
优点很明显,代码简短。
缺点:运行效率低下;容易造成栈的溢出。
下面我就以C++程序为例,通过使用二分法求一个方程如 x * x - 10 * x 在某个区间上的根。代码如下:
#include <iostream>
#include <cmath>
using namespace std;
inline float fx(float x)
{
return x * x - 10 * x;
}
float fun(int l, int r)
{
int m = (l + r) / 2;
float yl, yr, ym;
yl = fx(l);
yr = fx(r);
ym = fx(m);
<span style="white-space:pre"> </span>//递归的出口条件(精度范围)
if(fabs(ym) <= 1e-6)
return m;
<span style="white-space:pre"> </span>//中间变量的函数值与右侧变量的函数值同号,此时,左侧变量不变,只需要将中间变量转换成新的右侧变量进行新一轮的递归操作即可。
if(ym * yr >0)
{
return fun(l, m);
}
<span style="white-space:pre"> </span>//此时<span style="font-family: arial, 宋体, sans-serif;">中间变量的函数值与右侧变量的函数值异号,说明在这两个端点之间必定有一个方程的根。 此时,右侧变量不变,只需要将中间变量</span>
<span style="font-family: arial, 宋体, sans-serif;"> // </span><span style="font-family: arial, 宋体, sans-serif;">转换成新的左侧变量进行新一轮的递归操作即可。</span>
else //(ym * yr <0)
{
return fun(m, r);
}
}
int main()
{
int l, r;
cout << "请分别输入l, r" << endl;
cin >> l >> r;
cout<<endl;
while( fx(l) * fx(r) > 0 ) //确保两个
{
cout << "你刚刚输入的数值无效,请重新输入l, r" << endl;
cin >> l >> r;
}
cout << "最终求得的方程的解是:" << fun(l, r) << endl;
return 0;
}
二分算法比较容易理解:对于区间[a,b]上连续不断且f(a)·f(b)<0的函数y=f(x),通过不断地把函数f(x)的零点所在的区间一分为二,使区间的两个端点逐步逼近零点,进而得到零点近似值的方法叫二分法。当采用二分法时,必须保证所选择的两个端点的函数值的乘机必须是异号的,这样才能保证在这个区间内方程必有一根。
通过递归方式我们可以求得这个方程的近似解。在下一节的博客里,我们继续以这个方程为例,通过采用数组的方式来实现,同时比较这两种实现方式的效率。
以下是程序的运行结果的截图: