C语言函数的问题求帮助

调试并运行下面这段代码,会发现它无法得到n!的正确结果,请分析为什么会产生这样的结果?对此程序代码,只允许修改一条语句,将其改正,功能要求实现n!。

img


img

auto改为static

将return p修改为return p*Func(n-1);实现递归调用就可以了。

  • 你可以参考下这个问题的回答, 看看是否对你有帮助, 链接: https://ask.csdn.net/questions/7557905
  • 你也可以参考下这篇文章:编写一个算法实现n个整数类型数据的线性链表的逆置,并求出平均值
  • 除此之外, 这篇博客: C语言笔记:函数中的 6.1.4 练习4:求第n个斐波那契数。(不考虑溢出)。 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 斐波那契数列:1 1 2 3 5 8 13 21 34 55...

    规律:第n个数字等于n前两个数字之和

    Fib(n) = 1,                                   n <= 2

    Fib(n) = Fib(n - 1) + Fib(n - 2),   n <= 2

    递归思路:

    #include <stdio.h>
    
    int Fib(int a)
    {
        if (a > 2)
            return Fib(a - 1) + Fib(a - 2);
        else
            return 1;
    }
    
    int main()
    {
        int n = 0;
        scanf("%d", &n);
        int ret = Fib(n);
        printf("%d\n", ret);
        return 0;
    }

    无减枝操作的斐波那契递归代码效率很低下,如果参数比较大,那就会报错: stack overflow(栈溢出) 这样的信息。

    系统分配给程序的栈空间是有限的,但是如果出现了死循环,或者(死递归),这样有可能导致一 直开辟栈空间,最终产生栈空间耗尽的情况,即栈溢出。

    那如何解决上述的问题:

    1. 将递归改写成非递归。

    2. 使用static对象替代 nonstatic 局部对象

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

    非递归版本:

    第一次:

    a = 1,b = 1,c = a + b

    第二次:

    a = b,b = c,c = a + b

    所以非递归代码为:

    //更简洁的代码
    #include <stdio.h>
    
    int Fib(int n)
    {
        int a = 1;
        int b = 1;
        int c = 1;
        while(n > 2)
        {
            c = a + b;
            a = b;          
            b = c;   
            n--;
        }
        return c;
    }
    
    int main()
    {
        int n = 0;
        scanf("%d", &n);
        int ret = Fib(n);
        printf("%d\n", ret);
        return 0;
    }
    
    
    //初始构思的代码
    #include <stdio.h>
    
    int Fib(int n)
    {
        int a = 1;
        int b = 1;
        int c = 1;
        int i = 0;
        if (n <= 2)
            return 1;
        for (i = 0; i < n - 2; i++) //因为逻辑上当n > 2时,才开始循环,所以n=3对应第1次循环 所以 
                              
                                    //判断条件为i < n - 2
        {
            a = b;          
            b = c;
            c = a + b;
        }
        return c;
    }
    
    int main()
    {
        int n = 0;
        scanf("%d", &n);
        int ret = Fib(n);
        printf("%d\n", ret);
        return 0;
    }

    小结:

    1. 许多问题是以递归的形式进行解释的,这只是因为它比非递归的形式更为清晰。

    2. 但是这些问题的迭代实现往往比递归实现效率更高,虽然代码的可读性稍微差些。

    3. 当一个问题相当复杂,难以用迭代实现时,此时递归实现的简洁性便可以补偿它所带来的运行时开销。

  • 您还可以看一下 孙玖祥老师的图解数据结构与算法课程中的 汉诺塔问题代码实现小节, 巩固相关知识点