递归、递推与迭代
递归:函数本身调用自己,实现自身循环。例如:求斐波那契数
一列数的规则如下: 1、1、2、3、5、8、13、21、34...... 求第30位数是多少,
/// <summary> /// 用递归算法实现斐波那契 /// </summary> /// <param name="i"></param> /// <returns></returns> public static int Fibonacci_recursion(int i) { if (i <= 0) { return 0; } else if (i > 0 && i <= 2) { return 1; } else { return Fibonacci_recursion(i - 1) + Fibonacci_recursion(i - 2); } }
递推:根据其已有的数据和关系,逐步推导而得到结果的这个过程。
/// <summary> /// 递推算法实现斐波那契 /// </summary> /// <param name="n"></param> /// <returns></returns> public static int Fibonacci_recurrence(int n) { if (n <= 0) throw new ArgumentOutOfRangeException(); int a = 1,b = 1; for (int i = 3; i <= n; i++) { b = checked(a + b); a = b - a; } return b; }
例如传入的数为46,求第46位斐波那契数,递归与递推的结果与消耗时间分别是:
Stopwatch sw1 = new Stopwatch(); sw1.Start(); Console.WriteLine("递归结果:" + Logic.Fibonacci_recursion(46)); TimeSpan ts2 = sw1.Elapsed; Console.WriteLine("递归算法耗时:" + ts2); sw1.Stop(); Stopwatch sw2 = new Stopwatch(); sw2.Start(); Console.WriteLine("递推结果:" + Logic.Fibonacci_recurrence(46)); sw2.Stop(); TimeSpan ts1= sw2.Elapsed; Console.WriteLine("递推算法耗时:" + ts1);
由此可见递归和递推的算法消耗的时间差点一点半点,这个是因为递归每次都要压栈出栈,所以空间消耗要比非递归代码要大很多。而且如果递归深度太大,可能系统撑不住。
迭代比较简单了,迭代也是一种循环,与循环不同的是 运算变量的同时保存变量的值,保存的结果作为下次循环计算的初始值。 例如:C#中的 yield 关键字
public IEnumerable<int> GetList() { int i = 0; while (i < 10) { i++; yield return i; } }