首页 > 其他分享 >小白函数递归------新手

小白函数递归------新手

时间:2023-11-05 23:33:30浏览次数:29  
标签:10 递归 int ret num ------ 新手 fact

1. 递归是什么?

递归其实是⼀种解决问题的⽅法,在C语⾔中,递归就是函数⾃⼰调⽤⾃⼰。 

#include<stdio.h>
void print()
{
	printf("hehe");

	print();
}


int main()
{
	printf("hehe");

	print();

}

小白函数递归------新手_递归

在上面的函数中函数实现了自己调用自己,去实现我们想要去实现的功能,这种就是函数递归,上面那个是一种死递归


函数递归的思想其实就是我们实用体会大事化,小小事化了,我们来举一个n阶乘的例子。

n!=nx(n-1)x.........x1

一个正整数的阶乘是所有小于及等于该数正整数的积。

3!=3x2x1










int fact(int n)
{
	if (n == 0)
		return 1;
	else
		return  n * fact( n- 1);
}

int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret = fact(n);
	printf("%d", ret);
}

小白函数递归------新手_递归_02

然后我们会发现,当我们去求一个更高位数的阶乘。其实就等于这个位数乘以它减一的阶乘。比如我去求5的阶乘。

5的阶乘=1×2x3×4×5。

其实5的阶乘=4!x5。

我们怎么去分析这个,很简单当我们输入5的时候。我们调用了我们所使用的函数fact

根据判断条件,5不等于1,我们的N=5。

所以我们返回N×fact(n-1):此时此刻,我们就又调用了fact(n-1)即调用函数fact(4)根据条件又不成立,我们又要调用fact(3),…fact(2),fact(1),fact(0)

知道我们调用这个函数称为理,他会给我们返回1,fact(0)返回了1

         fact(1)=fact(0)*1=1

         fact(2)=fact(1)*2=2

         fact(3)=fact(2)*2=6

所以fact(4)返回了24,Fact(5)=5*24

我们得到了答案。


我们通过分析我们上面所写的代码

int fact(int n)
{
	if (n == 0)
		return 1;
	else
		return  n * fact( n- 1);
}

int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret = fact(n);
	printf("%d", ret);
}

我们明白递归的回归是有条件的。

我们可以利用这种想法,利用递归的思想去打印一个数的每一位。那我们如何思考?

当我们将一个数除10 就能够得到他出最后一位数之前的数,那么我们将这个数模10得到的余数。比如

1234/10=123

1234%10=4          

123/10=12

123%10=3

12/10=1

12%10=2

1/10=0

1%10=1

我们利用这种想法,加上函数的递归写出了下面这样的代码。

int division(int num)
{
	if (num / 10 == 0)
		return num;
	else
		printf("%d\n", num % 10);
		return  division(num / 10);

}



int main()
{
	int num = 0;
	scanf("%d", &num);
	int ret = division(num);

	printf("%d",ret);

}

小白函数递归------新手_递归_03



但是打印出来的是倒序,那我们如何有序的打印?

我们转变一下思想,其实我们可以利用,C语言中的除法,取得了前面的数。我们将我们取得的前面的数一一打印出来,然后再打印最后一位数

比如1234/10=123

123/10=12        12/10=1

然后利用if打印最后一位。

就这样我们就打印了前的数,然后再利用我模去打印最后一位数。我们就可以写出下面这样的代码

int division(int num)
{
	if (num>9)
	{
		 division(num/10);
	}
	printf("%d ", num % 10);

}



int main()
{
	int num = 0;
	scanf("%d", &num);
	int ret = division(num);

	printf("%d", ret);

}

小白函数递归------新手_堆栈_04

我们了解过开始的死递归,那么每一次调用都会申请空间吗?

每一次函数调用,都会向内存栈区上申请一块空间

这一块空间主要是用来存放函数的中局部变量,和函数调用过程中的上下文的信息这个一块空间一般叫:函数的运行时堆栈,也叫函数栈帧空间。

编译会自动根据需要开辟空间的!

栈帧我后面会讲的,Fact函数是可以产生正确的结果,但是在递归函数调用的过程中涉及一些运行时的开销。

在C语言中每一次函数调用,都要需要为本次函数调用在栈区申请一块内存空间来保存函数调用期间的各种局部变量的值,这块空间被称为运行时堆栈,或者函数线帧。

函数不返回,函数对应的栈帧空间就一直占用,所以如果函数调用中存在递归调用的话,每一次递归函数调用都会开辟属于自己的栈帧空间,直到函数递归不再继续,开始回归,才逐层释放栈帧空间。

所以如果采用函数递归的方式完成代码,递归层次太深,就会浪费太多的栈帧空间,也可能引起栈溢出



所以如果不想使用递归就得想其他的办法,通常就是迭代的方式,通常就是循环的方式)

利用循环去取得n的阶乘

int main() 
{
	int n = 0;
	scanf("%d", &n);
	int i = 0;
	int ret = 1;
	for (i = 1; i <= n; i++)
	{
		if (n == 0)
		{
			printf("0的阶乘:1");
		}
		else
		{

			ret = i * ret;

		}



	}

	printf("%d", ret);
}

小白函数递归------新手_函数调用_05



当我们去求第n个菲波那契数列,我们就会写出像下面这样的代码。

int series(int n)
{
	if (n == 1 || n == 2)
		return 1;
	else
	{
		return series(n - 1) + series(n - 2);
	}
}



int main()
{
	int n = 0;
	scanf("%d",&n);           
	int ret = series(n);

	printf("%d", ret);

}

小白函数递归------新手_递归_06





当我们去求第50个斐波那契数,计算就会很慢,那么我们就可以利用愉快的方式去解决这个问题比如循环




nt main()
{
	int a = 1;
	int b = 1;
	int num = 0;
	scanf("%d", &num);
	int ret = 0;
	while (num>=3)
	{
		ret = a + b;
		a = b;
		b = ret;
		num--;

	}
	printf("%d", ret);
	return 0;


}



小白函数递归------新手_递归_07




等我们完全了解上面两种方法的时候,那我们在什么时候去使用的,当我们使用递归可以运行没有过大的缺陷的时候,就可以使用递归

在这里我分享两个问题。

汉诺塔问题

青蛙跳台阶问题

如果想了解我后面会发表文章





标签:10,递归,int,ret,num,------,新手,fact
From: https://blog.51cto.com/u_16237653/8196759

相关文章

  • 题目四
    1,递归和非递归分别实现求第n个斐波那契数2,编写一个函数实现n的k次方,使用递归实现3,求n的阶乘,答案2,编写一个函数实现n的k次方,使用递归实现intmultiplication(intn,intk){ if(k==0) { return1; } else { returnn*multiplication(n,k-1); }}intmain()......
  • 畅网N100 的nas妖板来了
    畅网N100的nas妖板来了期待已久的畅网N100NAS主板来了,来几张谍照。紫铜散热6sata接口,看样子还是扩展1-5双M.2硬盘+pcie插槽,估计没有万兆。IO接口,这么一算,没有万兆是铁定的了散热一流的一大片铜块,主板全貌背面什么都没有。最后有的是预约。需要的可以来我定铺预约下......
  • 206-java修改图片文件的元属性值TIFF_TAG_SOFTWARE等
    base64的图片转为文件//base64的图片转为文件Stringbase64String=obj.getString("base64");byte[]imageBytes=java.util.Base64.getDecoder().decode(base64String);FileoutputFile=null;FiletmpPathDir=newFile(tmpPath);tmpPathDir.mkdirs();StringfileP......
  • LeetCode 精选100题-70题爬楼梯
    题目描述:假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?思路:第一阶楼梯:n=1,有一种方法f(1)=1;第二阶楼梯:n=2,有两种方法f(2)=2;当我们第一步爬了1个台阶时,我们可以有f(n-1)种方法爬到楼顶;当我们第一步爬了2......
  • TCP三次握手的机制
    工作原理描述1)客户端主动向服务器端发送请求SYN(SynchronizeSequenceNumbers),发送SYN=1,seq=n(随机序号)2)服务器端接收到请求后,进行确认,回复SYN=1,ACK=n+1(确认),seq=k(随机序号)3)客户端进行确认,回复SYN=1,ACK=k+1(确认),seq=n+1为什么需要三次握手TCP(transmissioncontrolprotocol)是可靠......
  • 【刷题笔记】101. Symmetric Tree
    题目Givenabinarytree,checkwhetheritisamirrorofitself(ie,symmetricarounditscenter).Forexample,thisbinarytree[1,2,2,3,4,4,3]issymmetric:1/\22/\/\3443Butthefollowing[1,2,2,null,3,null,3]isnot:1......
  • C++_18_多态 - 重写版
     多态:面向对象三大概念:封装、继承、多态!可想而知多态是何等的重要多态的概念以及前提条件:编译期绑定(静态联编):函数入口地址和函数名在编译期间绑定,即编译期间确定函数名和入口地址唯一对应运行期绑定(动态联编):函数入口地址和函数名在编译期间不绑定......
  • C++_17_多继承和虚基类 - 重写版
    多继承单继承:一个派生类只有一个基类,这就是单基类继承,简称“单继承”多继承:一个派生类允许有两个及以上的基类,这就是多基类继承,简称“多继承”单继承中,派生类是对基类的特例化,例如编程类书籍是书籍中的特例。而多继承中,派生类是所有基类的一种组合。在多继承中,派......
  • C++_15_友元函数和友元类 - 重写版
    友元函数和友元类友元函数:通过friend关键字,将不属于当前类的函数在当前类中加以声明,使其成为友元函数,同时该函数能够访问private属性的成员变量。友元类:有有元函数,自然也能有友元类,通过friend关键字,将类A在类B中声明,那么类A会成为类B的友元类注意:1、友......
  • C++_14_常量指针—this指针 - 重写版
    常量指针—this指针this指针:成员函数一般都会拥有一个常量指针(this),指向调用函数的对象,储存的是改对象的首地址(注意:静态成员函数是没有this指针的)//标准写法classbook{public:book(){this->price=0.0;this->title=NULL;}private:doubleprice;char......