数据结构与算法—递归recursion

目录

递归需要满足的三个条件

编程要点

递归复杂度

算法使用注意点

实例分析


递归需要满足的三个条件

1、一个问题需要分解为几个子问题的解

2、这个问题与分解之后的子问题,除了数据量不同,求解思路一样

3、终止条件

扫描二维码关注公众号,回复: 14650776 查看本文章

编程要点

        写出递推公式

        找到终止条件

        特殊条件检查

递归复杂度

在时间复杂度 O(n^2)

        递归,函数调用的数量较大时,非常耗时。

空间复杂度 O(n)

        递归调用一次就会在内存栈中保存一次现场数据,在分析递归代码空间复杂度时,需要额外考虑这部分开销。

算法使用注意点

1、警惕堆栈溢出

        函数调用会使用栈来保存临时变量,每调用一个函数,都会将临时变量封装为栈帧压如内存栈。系统栈空间一般都不大,递归层次很深,有堆栈溢出风险。最大深度比较小,如10,50,这样,否则警惕使用递归。因为当前线程剩余的栈空间大小事先无法计算,如果实时计算,代码过于复杂,影响可读性。

2、警惕重复计算

        现象,在递归实现时,如f(6) = f(5)+f(4);f(5)=f(4)+f(3),这样f(4)两次计算

        避免重复计算,可以使用一个数据结构(如散列表)来保存已经求解过的f(k),当递归遇到f(k)时,先看是否已经求解过了,避免重复计算。

实例分析

爬楼梯,一次可以上两个台阶,也可以上一个台阶。10个台阶有多少中方法?

公式:
f(n) = f(n-1)+f(n-2);条件 f(0) = 0,f(1) = 1,f(2) = 2

fun()函数,重复条件判断;fun1()没有使用重复条件

#include<stdio.h>
#include<stdlib.h>
#include<string.h>


int fun(int n,int *value)
{
	if(value[n]!=0)
	{
		return value[n];
	}
	value[n] = fun(n-1,value) + fun(n-2,value);
	return value[n];
}

int fun1(int n)
{
	if(n == 1) return 1;
	if(n == 2) return 2;
	return(fun1(n-1)+fun1(n-2));
}

void main()
{
	int n = 4;
	int ret = 0;
	printf("#############fun1#######\n");
	ret = fun1(n);
	printf("res1=%d\n",ret);
	
	printf("#############fun2#######\n");
	int *value = (int *)malloc(sizeof(int)*(n+1));
	if(value == NULL)
	{
		return;
	}


	memset(value,0,sizeof(int)*(n+1));
	value[0] = 0;
	value[1] = 1;
	value[2] = 2;

	ret = fun(n,value);

	printf("res=%d\n",ret);

	free(value);

}

猜你喜欢

转载自blog.csdn.net/WANGYONGZIXUE/article/details/129211991