递归

一切循环都可看作递归

1.计算斐波那契数列第n位的值。

斐波那契数列:1,1,2,3,5,8,13,21,34,55…
循环算法:

int fun(int n)
{
	int a = 1, b = 1, c = 1;
	for (int i = 3; i <= n; ++i)
	{
		c = a + b;
		a = b;
		b = c;
	}
	return c;

//时间复杂度:O(n)
递归算法:
在这里插入图片描述

int fun(int n)
{
	if (n <= 3)   return 1;
	else return fun(n - 1) + fun(n - 2);

}

上述算法存在重复求解项,时间复杂程度为2^n。以下算法可减少时间复杂度:

int  func(int n,int a,int b)
{
	if(n <= 2) return a;
	else  return func(n - 1, a + b, a)
}
int fun(int n)
{
	int a = 1,b = 1;
	return func(n, a, b);	
}

主函数:

int main()
{
	int n;
	scanf_s("%d", &n);
	printf("%d => %d ", n, fun(n));
	return 0;
}

2.递归实现求最大公约数

循环

unsiged int fac(unsigned int a,unsigned int b)
{
	while(b != 0)
	{
		int c = a % b;
		a = b;
		b = c;
	}
	return a;
}

递归

unsiged int fac(unsigned int a,unsigned int b)
{
	if(b == 0)  return a;
	else  return fac(b, a % b);   //将b赋给a,a%b赋给b
}

3.打印整型数组元素

主函数

int main()
{
	const int n = 10;
	int ar[n] = { 12,23,34,45,56,67,78,89,98,100 };
	Print_Ar(ar, n);
	return 0;
}

循环实现

void Print_Ar(int* br, int n)
{
	assert(br != nullptr);
	while (n > 0)
	{
		printf("%d ", br[n - 1]);
		--n;
	}
}

递归实现
(1)先打印,后递归

void Print_Ar(int* br, int n)
{
	assert(br != nullptr);
	if (n > 0)
	{
		printf("%d ", br[n - 1]);
	    Print_Ar(br, n-1);
	}
}

先打印,后递归,分别打印br[9],…,br[0].
在这里插入图片描述
(2)先递归,后打印

void Print_Ar(int* br, int n)
{
	assert(br != nullptr);
	if (n > 0)
	{
		Print_Ar(br, n-1);
		printf("%d ", br[n - 1]);
	}
}

先递归,后打印。在回退的过程中打印,分别打印br[0],…,br[9].
在这里插入图片描述
(3).递归实现的几个错误
一般来说,递归时不要出现自加,自减
错误示例1:(n - -)

void Print_Ar(int* br, int n)
{
	assert(br != nullptr);
	if (n > 0)
	{
		Print_Ar(br, n--);       //ERROR
		printf("%d ", br[n - 1]);
	}
}
Print_Ar(br, n--);
printf("%d ", br[n - 1]);

n- -,先赋值再减:首先取n = 10,先将10赋给下一次Print_Ar(br,n)中的n,然后自减,打印br[9],下一次执行时,依旧是Print_Ar(br,10),如此往复,无限递归,导致栈溢出。
错误示例2:(- - n)

void Print_Ar(int* br, int n)
{
	assert(br != nullptr);
	if (n > 0)
	{
		Print_Ar(br, --n);       //ERROR
		printf("%d ", br[n - 1]);
	}
}

(- -n):先自减再赋值。递归过程中分别将n = 9,…3,2,1,0赋给下一个函数,在回退时,n = 0不执行递归语句,回退一位,此时n为0,打印br[n-1]为br[-1],越界打印,会出现一个随机值,结果如下:
在这里插入图片描述
错误示例2如果先打印再递归,则正确:

void Print_Ar(int* br, int n)
{
	assert(br != nullptr);
	if (n > 0)
	{
		printf("%d ", br[n - 1]);
		Print_Ar(br, --n);      
	}
}

依次打印br[9],br[8],…,br[0]。
在这里插入图片描述

4.在无序数组中查找给定值,返回其下标

主函数:

int main()
{
	const int n = 10;
	int ar[n] = {34,56,12,23,78,89,90,100,67,45}
	int val;
	scanf_s("%d", &val);
	int pos = FindValue(ar, n, val);
	return 0;
}

循环实现

int FindValue(int* br, int n, int val)
{
	assert(br != nullptr);
	int pos = n - 1;
	while(pos >= 0 && br[pos] != val)
	{
		--pos;
	}
	return pos;
}

递归实现:

int FindValue(int* br,int n,int val)
{
	assert(br != nullptr);
	if(n < 1 || br[n-1] = val)      //n为0,或值等于val时,返回-1,或下标
	{
		return n-1;
	}
	else
	{
		return FindValue(br, n-1, val)   //否则将n-1赋给n
	}
}

易错:

...
else
	{
	  FindValue(br, n-1, val)   //否则将n-1赋给n
	}

若无return ,则回退过程返回的数据无法接收哦。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值