完全自学C(干货) —— 递归

递归 recursion

  • 程序调用自身的编程技巧,称为递归;
  • 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解;
  • 递归的策略只需少量的程序就可描述出解题过程所需的多次重复计算,大大减少程序的代码量;
  • 注意思想方式在于:大事化小;

必要条件

  • 存在限制条件,当满足这个限制条件的时候,递归将不在继续,否则无限调用;
  • 每次递归调用之后越来越接近这个限制条件;
//如n=1234,则打印1 2 3 4
void print(unsigned int n)
{
	if (n > 9)
		print(n / 10);
	printf("%d ",n % 10);
}
//编写函数不允许创建临时变量,求字符串的长度
int myStrlen(char* str)
{
    if ('\0' == *str) //限制条件
        return 0;
    else
        return 1 + myStrlen(str + 1); //越来越接近‘\0’
}
 
int main()
{
    char str[] = "abcd";
    printf("%d", myStrlen(str));
}

注:递归层次不要太深,否则也会出现栈溢出情况;因为每调用一次即开辟一块内存,如果调用次数过多,即会有可能造成栈溢出;

//递归方式
//n的阶乘
int factorial (int n) 
{
    if(n <= 1)
        return 1;
    else
        return n * factorial(n-1);
}
//注:求10000的阶乘时程序会崩溃;
//递归方式
//斐波那契
int fib(int n)
{
    if(n <= 2)
        return 1;
    else
        return fib(n - 1) + fib(n - 2);
}
//注:求50以上的斐波那契时,非常耗时,有可能栈溢出;

注:

  • 栈区,局部变量、函数形参;
  • 堆区,动态内存(malloc/calloc/realloc);
  • 静态区,全局变量、静态变量;

程序员的知乎:Stack Overflow - Where Developers Learn, Share, & Build Careers

解决办法

  • 将递归改写成非递归,如循环迭代;
  • 使用static对象替代nonstatic局部对象。在递归函数设计中,可以使用static对象替代nonstatic局部对象(即栈对象),这不仅可以减少每次递归调用和返回时产生和释放nonstatic对象的开销, 而且static对象还可以保存递归调用的中间状态,并且可为各个调用层所访问;

提示:

  • 许多问题是以递归形式进行解释的,这只是因为它比非递归形式更为清晰;
  • 迭代实现往往比递归实现效率更高,但代码的可读性稍微差些;
  • 当一个问题相当复杂,难以迭代实现时,递归实现的简洁性可补偿运行时的开销;
//循环迭代方式
//n的阶乘
int factorial(int n)
{
    int result = 1;
    while (n > 1)
    {
        result *= n;
        n -= 1;
    }
    return result;
}
//循环迭代方式
//斐波那契
int fib(int n)
{
    int result;
    int prepre;
    int pre;

    result = pre = 1;
    while (n > 2)
    {
        n -= 1;
        prepre = pre;
        pre = result;
        result = prepre + pre;
    }
    return result;
}

案例

  • 汉诺塔问题
  • 青蛙跳台阶问题

好的,我很乐意为您介绍一下C语言递归函数和嵌套函数的概念,并提供一些相关的实验答案思路。 递归函数: 递归函数是指在函数体内调用自身的一种函数。它通常用于解决可以被分解为相似子问题的情况。递归函数需要包含两个关键要素: 1. 基本情况(base case):用于终止递归的条件。 2. 递归情况(recursive case):函数调用自身的部分。 嵌套函数: 嵌套函数是指在一个函数的内部定义另一个函数。在C语言中,标准C并不直接支持嵌套函数,但一些编译器(如GCC)提供了扩展来实现这一功能。 实验九可能涉及的题目示例及解答思路: 1. 使用递归实现斐波那契数列: ```c #include <stdio.h> int fibonacci(int n) { if (n <= 1) return n; else return fibonacci(n-2); } int main() { int n, i; printf("Enter the number of terms: "); scanf("%d", &n); for (i = 0; i < n; i++) printf("%d ", fibonacci(i)); return 0; } ``` 2. 使用递归实现阶乘函数: ```c #include <stdio.h> long factorial(int n) { if (n == 0) return 1; else return n * factorial(n-1); } int main() { int num; printf("Enter a number: "); scanf("%d", &num); printf("Factorial of %d is %ld\n", num, factorial(num)); return 0; } ``` 3. 嵌套函数示例(GCC编译器): ```c #include <stdio.h> void outerFunction() { printf("This is the outer function.\n"); void innerFunction() { printf("This is the inner function.\n"); } innerFunction(); } int main() { outerFunction(); return 0; } ``` 这些例子展示了递归和嵌套函数的基本用法。在实际实验中,你可能需要根据具体要求进行适当的修改和扩展。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值