递归的简单理解

1.什么是递归

    程序调用自身的编程技巧称为递归。它是一个过程或函数在其定义或说明中直接或间接调用自身的一种方法。简单来说它就是把一个较大较复杂的问题简化成一个与原问题相似的规模较小的问题来求解,递归策略只需要少量的程序就可以描述出解题过程所需要的多次重复计算,可以大大减少程序的代码量。

2.递归的两个必要条件

1)存在限制条件,当满足这个限制条件时,递归就不再继续。

2)每次递归调用之后越来越接近这个限制条件。

3..举例

        下面我们来从以下例子进项思考

  例1:  输入一个数,将这个数按顺序分解:

#include <stdio.h>

void print(int m)
{
	if (m > 9)
	{
		print(m / 10);                //此处就是递归,自己调用自己;
		printf("%d ", m%10);
	}
	else
		printf("%d ", m);
}

int main()
{
	int a = 0;
	printf("请输出你要分解的数:");
	scanf("%d", &a);
	print(a);
	return 0;
}

例2: 编写函数,求字符串的长度:

    一般方法书写:

#include <stdio.h>

int my_len(char* str)
{
	int count = 0;
	while (*str != '\0')
	{
		count++;
		str++;
	}
	return count;
}

int main()
{
	char arr[] = "bit";
	int len = my_len(arr);
	printf("%d", len);
	return 0;
}

    用递归方法改进:

int my_len(char* str)
{
	if (*str != '\0')
		return 1+my_len(str+1);    //此处用的递归;
	else
		return 0;
}

int main()
{
	char arr[] = "bit";
	int len = my_len(arr);
	printf("%d", len);
	return 0;
}

例3:求一个数的阶乘:

    一般算法:

#include <stdio.h>

int Facl(int m)
{
	int count = 1;
	  for (int i = 1; i <= m; i++)
	{
		  count *= i;
	}
	  return count;
}

int main()
{
	int n = 0;
	int ret = 0;
	printf("请输入阶乘数:");
	scanf("%d", &n);
	ret = Facl(n);
	printf("%d", ret);
	return 0;

}

    递归算法:

#include <stdio.h>

int Facl(int m)
{
	if (m >= 1)
	{
		return  m * Facl(m - 1);      //用到递归的地方;
	 }
	else
	{
		return 1;
	}
}

int main()
{
	int n = 0;
	int ret = 0;
	printf("请输入阶乘数:");
	scanf("%d", &n);
	ret = Facl(n);
	printf("%d", ret);
	return 0;

}

但有些情况用递归函数来求解会有些不太妙,如下:

求第n位非彼拉切数列的数是多少:

#include <stdio.h>

int Fib(int m)
{
	if (m <= 2)
	{
		return 1;
	}
	if (m > 2)
	{
		return Fib(m - 1) + Fib(m - 2);     //用到递归的地方;
	}
}

int main()
{
	int num = 0;
	int n = 0;
	printf("请输入第n个位置:");
	scanf("%d",&n);
	num = Fib(n);
	printf("%d", num);
}

这个问题用递归来求有以下缺点:

1.时间复杂度高:递归方法在计算过程中会进行大量的重复计算,导致时间复杂度较高。每次递归调 用都需要重新计算之前已经计算过的值,这样会浪费大量的时间和计算资源。

2.栈溢出:递归方法使用函数调用栈来保存每一层递归调用的状态,如果递归深度过大,函数调用栈可能会溢出。非彼拉切数列的计算过程中,递归深度会随着数列项数的增加而增加,当数列项数较大时,可能会导致栈溢出的问题。

3.内存占用大:递归方法需要保存每一层递归的状态信息,包括参数、局部变量等。如果非彼拉切数列的项数较大,递归方法会占用大量的内存空间,可能导致内存不足的问题。

4.可读性差:递归方法的代码结构复杂,理解起来相对困难。递归调用会形成一种嵌套的结构,代码逻辑不够直观,容易出现逻辑错误和调试困难。

用循环求解:

#include<stdio.h>

int xunhuan(int j)
{
	if (j <= 2)
	{
		return 1;
	}
	if(j > 2)
	{
		int a = 1;
		int b = 1;
		int c = 0;
		for(int d = 1;d <=j - 2;d++)
		{
			c = a + b;
			a = b;
			b = c;
		}
		return c;
	}
}

int main()
{
	int n = 0;
	int m = 0;
	printf("请输入第几位:");
		scanf("%d", &n);
	m = xunhuan(n);
	printf("%d", m);
	return 0;
}

4.栈溢出

    使用递归导致栈溢出的主要原因是没有添加限制条件,但添加了限制条件不能说一定不会导致栈溢出。同样满足文章开头所说的递归的两个必要条件,递归不一定就不会出现栈溢出。比如下面这段代码:

#include <stdio.h>

void test(int m)
{
	if(m < 10000)
	{
	test (m+1);
    }
     
}

int main()
{
	test(1);
	return 0;
}

会出现以下状况

 希望能够帮到大家!!!

如有错误还请大家指出!!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值