递归算法经典实例小结(C#实现)
一 、递归算法简介
在数学与计算机科学中,递归是指在函数的定义中使用函数自身的方法。
递归算法是一种直接或者间接地调用自身算法的过程。在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解。
递归算法解决问题的特点:
(1) 递归就是在过程或函数里调用自身。
(2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。
(3) 递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。所以一般不提倡用递归算法设计程序。
(4) 在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。所以一般不提倡用递归算法设计程序。在实际编程中尤其要注意栈溢出问题。
借助递归方法,我们可以把一个相对复杂的问题转化为一个与原问题相似的规模较小的问题来求解,递归方法只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。但在带来便捷的同时,也会有一些缺点,也即:通常用递归方法的运行效率不高。
1、菲波那切数列(Fibonacci)
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, …,总之,就是第N(N > 2)个数等于第(N - 1)个数和(N - 2)个数的和。
(1)不用递归时
int[] a=new int[30]; a[0] = 1; a[1] = 1; int qian = a[0]; int hou = a[1]; for (int i = 2; i < a.Length; i++) { a[i] = qian + hou; qian = hou; hou = a[i]; } Console.WriteLine(a[6]);
(2)使用递归时
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 练习作业 { class Program { static void Main(string[] args) { //调用方法 int a = Foo(30); Console.WriteLine(a); Console.ReadLine(); } //方法 public static int Foo(int i) { if (i <= 0) { return 0; } else if (i > 0 && i <= 2) { return 1; } else { return Foo(i - 2) + Foo(i - 1); } } } }
2、阶乘
阶乘(!)是小于某个数的所有正整数的乘积。
0! = 1
1! = 1
2! = 2 * 1! = 2
3! = 3 * 2! = 6
...
n! = n * (n - 1)!
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 练习作业 { class Program { static void Main(string[] args) { //调用方法 int a = jiecheng(3); Console.WriteLine(a); Console.ReadLine(); } //方法 public static int jiecheng(int n) { int sum; if (n == 0) //限制条件,对该方法调用自己做了限制 { sum = 1; } else { sum=n * jiecheng(n - 1); } return sum; } } }
3、汉诺塔问题
有三根杆子A,B,C。A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至C杆:
1、每次只能移动一个圆盘;
2、大盘不能叠在小盘上面。
提示:可将圆盘临时置于B杆,也可将从A杆移出的圆盘重新移回A杆,但都必须遵循上述两条规则。
问:如何移?最少要移动多少次?
static void Main(string[] args) { Hanoi(5, 'A', 'B', 'C'); Console.ReadLine(); } public static void Hanoi(int n ,char A, char B, char C) { //汉诺塔问题 //将n个盘子从A座借助B座,移到C座 if (n == 1) Move(A, C); else { Hanoi(n - 1, A, C, B); Move(A, C); Hanoi(n - 1, B, A, C); } } public static void Move(char startPlace, char endPlace) { Console.WriteLine("Move {0} To {1}",startPlace,endPlace); }
4、查找文件
public ArrayList al=new ArrayList(); //我把ArrayList当成动态数组用,非常好用 public void GetAllDirList(string strBaseDir) { DirectoryInfo di=new DirectoryInfo(strBaseDir); DirectoryInfo[] diA=di.GetDirectories(); for(int i=0;i<diA.Length;i++) { al.Add(diA[i].FullName); //diA[i].FullName是某个子目录的绝对地址,把它记录在ArrayList中 GetAllDirList(diA[i].FullName); //注意:这里使用C#递归的方法 } }