1.递归
函数的递归可以通过字面意思分为两部分:递推和回归(下面解释的图片中,红线是递推的过程,黑线是回归的过程),它是程序调用自身的编程技巧,通常把一个大型的问题层层转化为一个与原问题相似的规模较小的问题来求解,它的主要思考方式在于:把大事化小。
下面我们通过一些代码来深度剖析递归:
一、按顺序打印出一个数的千位、百位、十位、个位
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void Print(int n)
{
if (n>9)
{
Print(n / 10); //递归
}
printf("%d ", n % 10); //输出
}
int main()
{
int num = 0;
//输入
scanf("%d", &num);
Print(num);
return 0;
}
那么这串代码是如何实现的呢,下面通过画图来告诉大家原理:
二、使用递归计算字符串的个数
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int is_strlen(char* str)
{
if (*str != '\0') {
return 1 + is_strlen(str+1); //递归,str为地址+1
}
else
return 0;
}
int main()
{
char arr[10] = "abcdef"; //strlen()计算\0前面的字符个数
int m = is_strlen(arr); //数组名是数组首元素的地址
printf("%d", m);
return 0;
}
PS:下面图示只画出计算abc的计算过程(即假设字符串只有abc)
三、计算n的阶乘
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int fac(int n)
{
if (n <= 1)
return 1;
else
return n * fac(n-1); //递归n*(n-1的阶乘)
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = fac(n);
printf("%d", ret);
return 0;
}
通过上面的代码,我们可以知道递归的两个必要条件:1、存在限制条件,当满足这个限制条件时递归便不再继续。2、每次递归过后越来越接近这个条件。
2.迭代
迭代是使用重复的过程来解决问题的一种方法,通常通过循环结构(如for
循环或while
循环)来实现。与递归不同,迭代不涉及函数自身的调用,而是通过修改循环变量和条件来反复执行代码块。
其实上面递归能写出来的代码,迭代也可以实现,下面展示代码的迭代展示:
一、按顺序打印出一个数的千位、百位、十位、个位
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void Print(int n)
{
int i = 1000;
while(i>=1)
{
printf("%d ", n / i % 10);
i = i / 10; //每完成一次循环i除以10
}
}
int main()
{
int num = 0;
scanf("%d", &num);
Print(num);
return 0;
}
二、使用递归计算字符串的个数
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int is_strlen(char* str)
{
int count = 0; //定义一个计数器
while (*str != '\0')
{
count++;
str++; //指针++,指向下一个元素
}
return count;
}
int main()
{
char arr[10] = "abcdef"; //strlen()计算\0前面的字符个数
int m= is_strlen(arr);
printf("%d", m);
return 0;
}
三、计算n的阶乘
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int fac(int n)
{
int i = 0;
int ret = 1;
for (i = 1; i <=n; i++)
{
ret = ret * i;
}
return ret;
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = fac(n);
printf("%d", ret);
return 0;
}
三、两者的优缺点
递归:
优点:1、逻辑性强,对于一些问题,递归的方式接近于数学定义,使得实现的逻辑更为自然易懂。2、更容易实现复杂算法,很多复杂的算法和数据结构在递归形式下更为直观。
缺点:1、性能开销:每次递归调用都会产生一个堆栈帧,增加了内存消耗可能导致性能下降。2、栈溢出风险:对于深层递归可能导致运行时栈溢出,尤其在处理大数据集或深度数据结构时。3、调试难度大。
迭代:
优点:1、性能优越:迭代比递归更高效,避免重复调用函数调用开销。2、内存占用低。3、避免栈溢出问题。
缺点:1、代码可读性差。2、适用范围比递归小。
最后,通过计算斐波那契数列的第50个元素来说明它们的性能差异:
递归:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int count = 0;
int Fib(int n)
{
if (n == 3)
count++;
if (n <= 2)
return 1;
else
return Fib(n - 1) + Fib(n - 2);
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = Fib(n);
printf("%d", ret);
printf("第三个斐波那契数被使用的次数%d", count);
return 0;
}
可以看到光标一直卡在50下方,无法输出,这是因为递归层数过多导致的。
迭代:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int Fib(int n)
{
int a = 1;
int b = 1;
int c = 1;
while (n >= 3)
{
c = a + b;
a = b;
b = c;
n--;
}
return c;
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = Fib(n);
printf("%d", ret);
return 0;
}
可以看到,程序能够得出运算结果,只是因为int类型范围不够输出,而输出了错误结果,由此可以看出迭代的性能相比递归更好。
新人博主,希望大家多多三连,博主在此谢过大家了!!!