函数的递归
//将1234这样的数以1 2 3 4这样的形式输出
//要以这样的形式输出,就要使用递归的形式
//这儿创建一个函数,用递归的方式将1234拆为1 2 3 4 的形式
#include<stdio.h>
#include<windows.h>
int Recurisive(int x)
{
if (x > 9)
{
Recurisive(x/10);
}
printf("%d", x % 10);
}
int main()
{
//调用一个Recursive函数来实现相应的目的
int x = 1234;
Recurisive(x);
system(“pause”);
return 0;
}
关于这个函数中递归部分的理解:
这个函数中的递归就为以下部分
int Recurisive(int x)
{
if (x > 9)
{
Recurisive(x/10);
}
printf("%d", x % 10);
}
对这部分进行分析
假如传递进来的形参为1234,就有当x大于9时就会出现Recurisive()函数反复调用自己的情况
其中递归的逻辑如下
首先Recurisive函数是由两部分组成 我们将if语句包含的部分称为函数的第一部分,将if语句不包含的部分称为函数的第二部分
则函数的执行逻辑为
Recurisive(1234)(执行第一部分)
Recurisive(123)(因为这是函数自身调用自身的请况,其实执行的还是函数的第一部分)
Recurisive(12)(执行的是Recurisive函数的第一部分的一部分)
Recurisive(1)(执行的是Recurisive函数第一部分的一部分)
上面体现的递归中递的部分,而接下来体现的是递归中归的部分
因为函数反复调用自身的原因,所以它形成了一个自上向下的过程,而在接下来函数接受函数第一部分传递的值时,它的过程是一个自下向上的传递过程
Recurisive(1)//首先传入函数第二部分进行执行的的是1,就像电影盗梦空间中一样,进入时是从最外面的一层梦,然后一层一层的进入最里面的一层梦.而从梦中出来时,先要结束的是最内层的梦
Recurisive(12)
Recurisive(123)
Recurisive(1234)
个人理解这道题的递归就是这种逻辑,后面如有更好哦的方法,再进行改进
//实现求一个字符数组的长度
//c语言中字符串本质上字符数组模拟过来的
//字符数组本质上和普通的数组没有什么区别,只不过它数组中每一个元素都是char型的
//c语言中虽然字符串是一个数组,但是我们也可以通过一个char* 指针来指向数组的第一个元素,来表示一个字符数组
//创建一个strlen函数用非递归的方式来求字符数组的长度
//定义一个指针,指向数组的第一个数,这样也可以表示这个数组
//我们通过递加指针的方式,遍历整个数组,进而求出字符数组的长度
//注意:这个放在不同的位置中,所表示的含义是不同的
//当你要声明或者定义一个变量时,就要将变量类型和写在一起 类似 char* str 表示这是一个指针
//注意:此处的char* 表示的就是一种数据类型,和int float double 表示的关系是一样的
//而写为str 这种形式,表示了解引用,代表了指针所指位置所包含的内容
#include<stdio.h>
#include<windows.h>
int Strlen(char str)
{
//定义一个名为count的数字,当指针的位置向右移动一位时,count+1.
int count=0;
//创建一个循环,因为根据c语言数组的特点,数组都以’\0’结尾
//所以我们使用解引用,当解引用的表示的为’\0’时,说明这个数组已经遍历完成
//这儿’\0’表示的就是ASCII码表中值为0的数
while (*str != ‘\0’)
{
++count;
//遍历整个字符串数组,直到结束
++str;
}
return count;
}
int main()
{
//调用一个我创建的strlen函数来计算一个字符数组的长度
printf("%d\n", Strlen());
system(“pause”);
return 0;
}
//通过递归的方式来计算一个数组的长度
int Strlen(const char* str)
{
//设置一个出口
//当字符数组的第一个字符为’\0’时,则证明这个数组的长度为0
if (*str == ‘\0’)
{
return 0;
}
else
{
//创建一个递归的形式
return 1 + Strlen(str + 1);
}
}
int main()
{
//调用一个我创建的strlen函数来计算一个字符数组的长度
//此处pi所占的内存空间为3
//但是这个字符数组的长度为2,注意(\0)不计入字符数组的长度
printf("%d\n", Strlen(“hello”));
system(“pause”);
return 0;
}
斐波那契数列
关于斐波那契额数列,百度上的定义是这样的,如果一个数列满足,某一项的值是前两项之和,类似1,1,2,3,5,8这样的数列,我们称这样的数列为斐波那契数列
//创建一个实现斐波那契数列的函数
#include<stdio.h>
#include<windows.h>
int Fun(int n)
{
//我们观察斐波那契数列可以看到,这个数列的前两项的值都为1
//所以在前两项的情况下,我们输出的值为1
//此处的为逻辑或,得到的结果为0或者1,要区分按位或与之的区别,按位或得到的结果为一个数字,只不过是按照二进制进行计算的
if (n == 1 || n == 2)
{
return 1;
}
else
{
return Fun(n - 1) + Fun(n - 2);
}
}
int main()
{
int n=1;
//调用一个Fun函数来输出一个斐波那契数列
//先输出前10项
for (n = 1; n < 10; n++)
{
printf("%d\n", Fun(n));
}
system(“pause”);
return 0;
}
输出斐波那契数列的前10项
当我们要计算前100个数字时,因为数字过大,我们发现计算机无法输出
所以我们计算前40个数字,结果如下
我们在运行程序的过程中可以看到,程序的运算时间极长,所以我们思考是什么原因
运算规律 f(40)
f(39) f(38)
f(38) f(37) f(37) f(36)
…
我们可以看到要计算一个数的值,就要计算他底层的值,所以越底层的值计算的次数越多
假如,我们来计算一下,要计算第40个数,需要计算多少次第3项
通过程序的运行,我们可以看到这个数是很大的,这样就说明程序做了很多没有必要的计算,加长了程序的运行时间,所以我们需要对程序进行优化.
#include<stdio.h>
#include<windows.h>
int Fun(int n)
{
//因为前两项为1,所以单独输出
if (n == 1 || n == 2)
{
return 1;
}
//定义两个数来表示这个数列的前两项
int num1 = 1;
int num2 = 1;
int i;
int result;
//因为前两项单独输出,所以从第三项来开始计算
for (i = 3; i <=n; i++)
{
//第三项等于第一项与第二项之和
result = num1 + num2;
num1 = num2;
//当运算结束后,将第二项的值赋值给第一项
//将结果,即第三项的值赋值给第二项
//即整个数列向后移动
num2 = result;
}
return result;
}
int main()
{
int n=40;
//调用一个Fun()函数来进行计算
printf("%d", Fun(n));
system(“pause”);
return 0;
}
我们的通过运行可以发现,我们的计算速度大大提高
所以,通常情况解决一个问题,我们可以通过递归的方式也可以通过非递归的方式
递归:代码相对更简单,更直观,但是运行效率大大下降
非递归:即循环的方式,相对于递归而言,代码更加复杂,但是运行效率却大大上升