1. 递归是什么?
递归是学习C语⾔函数绕不开的⼀个话题,那什么是递归呢? 递归其实是⼀种解决问题的⽅法,在C语⾔中,递归就是函数⾃⼰调⽤⾃⼰。“递”的意思是递推,“归”意思是回归。这样解释不太好理解,下面举例。
前置打印
下面我们首先举出一个例子:实现一个函数print1,功能是接收一个整形数据,打印此整形的每一位的数字,比如输入15867,就打印1 5 8 6 7。
void print1(int num)
{
if (num < 10)
{
printf("%d ", num);
}
else
{
print1(num / 10);
printf("%d ", num%10);
}
}
就拿刚才15867的例子,先判断大于还是小于10,15867显然执行else部分的代码,于是15867就分解成1586和7,1586作为一个新的参数输入进print1函数,1586又分解成158和6.......以此类推。
但需要注意的是,这里属于后置打印,就是在“回归”的时候进行打印,printf放在print1的后面,所以说在递推的时候是不进行打印的。
后置打印
为了深层次地感受“递推”与“回归”,我又写了print2函数,功能与print1函数一样,但此次用的是前置打印,也就是在递推的时候就打印。
//判断数字是几位数的函数
int count(int x)
{
int t = 0;
while (x!=0)
{
x /= 10;
t++;
}
return t;
}
void print2(int num)//这是前置打印,递推时的打印
{
//判断num是几位数
if (num < 10)
{
printf("%d ", num);
}
else
{
int a = count(num);
int b = pow(10, a-1);
printf("%d ", num / b);
print2(num % b);
}
}
首先我先定义了一个函数count用于计算输入的整形的位数。又是15867的例子,int a是15867的位数,也就是5,b此时是10000,15864/10000得到的1就是第一位的数字,显然将15867分解成1和5867.所以这里的1是要最先打印的,5是第二个打印的。因此前置打印。
来看一下完整的代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<math.h>
void print1(int num)//这是后置打印,回归时的打印
{
if (num < 10)
{
printf("%d ", num);
}
else
{
print1(num / 10);
printf("%d ", num%10);
}
}
//判断数字是几位数的函数
int count(int x)
{
int t = 0;
while (x!=0)
{
x /= 10;
t++;
}
return t;
}
void print2(int num)//这是前置打印,递推时的打印
{
//判断num是几位数
if (num < 10)
{
printf("%d ", num);
}
else
{
int a = count(num);
int b = pow(10, a-1);
printf("%d ", num / b);
print2(num % b);
}
}
int main()
{
print1(13579);
printf("\n");
print2(1345);
}
执行成果
2.函数递归中的数学思想
函数的递归实质上运用了数学中的“数学归纳法”,我们首先要直到n=1(,n=2)时的函数值,然后根据递推的规律一项一项地往后推,这种方法极大有的时候地简化了代码,使⽤了⼤事化⼩的思路。我们来实现斐波那契数列。
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int count = 0;
int Fib(int n)
{
if (n <= 2)
return 1;
else
return Fib(n - 1) + Fib(n - 2);
}
int main()
{
int a = Fib(20);
printf("%d", a);
}
这里的代码很好解释,就不进行详细解释。我们可以看到此代码仅仅几行就描述出斐波那契数列,十分简洁,但还是要提醒一点,函数的递归虽然简化了代码,但是并不意味着提高了运行效率。
我们试着将先前的20改成50,会发现电脑一直计算不出这个数字,原因时重复的计算太多,导致效率极其低。而根据我们正常人的思维,第50位似乎并没有如此难计算。
int main()
{
int a = Fib(50);
printf("%d", a);
}
3.递归虽好,可别忘了迭代
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int count = 0;
int Fib(int n)
{
int a = 1;
int b = 1;
int c = 1;
while (n > 2)
{
c = a + b;
a = b;
b = c;
n--;
}
return c;
}
int main()
{
int a = Fib(20);
printf("%d", a);
}
这个迭代的代码就非常符合人们正常的思路,避免了重复的计算,其中c相当于fib(n),a和b相当于fib(n-1),fib(n-2)。每执行一次循环,b->a,c->b,然后c重新进行计算,相当于三个变量同时往后移动了一位。极大的提高了代码的运行效率。
由于编者水平有限,缺点和疏漏在所难免,恳请大家不吝指正,万分感激。