这周对于算法开始了相对系统的学习,嗯,也算是弥补一下自己之前的不足,劣势;
从递归开始吧:
递归, 与循环,二者在理论上是等价的,一般的递归,我们也总可以,将其表示为循环的格式,任何循环同样也可以改写成递归的形式,这里是一些循环改写递归的方法与例子:
听说哈,有的语言是没有递归的;
递归的改写,重要的是,发现循环之中的相似性;
下面是实例:
- //打印从0到9的整数;
- #include <stdio.h>
- #include <conio.h>
- void main()
- {
- for (int i = 0; i < 10; i++)
- {
- printf("%d\n",i);
- }
- _getch();
- }
这样就是一个初步的循环输出的样式,现在要改写为递归的格式,该如何改变。
递归,之前听有一位老师讲过,实质上始终踢皮球的做法
以上面这个例字来假设,要想打印从0-9的整数,想象,这个工作,被推到我身上,但是我又不能原封不动地将所有工作交给下属,我多少得做一些,所以,我可以这么干:
定义一个函数,打印一个数字;
- int print(int n)
- {
- f(n-1);//打印0-(n-1)
- printf("%d",n);//打印n
- }
就是我干一部分工作,比如说我打印n,将剩下的所有工作推给下属,然后,同理,下属也是想要推卸责任,下属只打印了n-1的那一份,又将剩下的工作推给下属的下属………………以此类推
但是,这里就出现了递归的一个限制,凡是递归,实质上是函数不断调用自身的做法,如果这么无限次调用下去,那就是死循环,我们要考虑如何从这个递归的死循环里跳出来,就
是,找到出口
- int f(int n)
- {
- if (n>0)
- {
- f(n - 1);//打印0-(n-1)
- }
- printf("%d", n);//打印n
- }
这里加入了一个限制,限制了n的取值,当n>0的时候,递归才能继续调用。
当然如果没有相似性,就需要我们主动构造相似性,有一些循环不能找到相似性的原因可能是缺少参数,这个时候就需要找到一个参数作为函数调用之间的桥梁,保证其相似性,构造递归
复杂一点的例子:
数组所有元素求和
原:
- #include <stdio.h>
- #include <conio.h>
- #define N 10
- int add(int a[]);
- void main()
- {
- int a[N] = { 2,5,3,9,12,7 };
- int sum;
- sum = add(a);
- printf("%d\n", sum);
- _getch();
- }
- int add(int a[])
- {
- int x = 0;
- for (int i = 0; i < N; i++)
- {
- x += a[i];
- }
- return x;
- }
这里要想将这个循环改写成递归的形式,做法如下:
- int f(int a[],int begin) //求a数组中从begin开始到结束的元素和
- {
- if(begin==N) return 0;
- int x= f(a,begin+1);
- return x + a[begin];
- }
- void main()
- {
- int a[N] = { 2,5,3,9,12,7 };
- int sum;
- sum = f(a,0);//从第零项开始累加
- printf("%d\n", sum);
- _getch(};
- }
这个就是一些简单的递归的变换构造的问题的做法
献丑
f(n-1);//打印0-(n-1)
printf("%d",n);//打印n