算法:阶乘的五种算法

算法:阶乘的五种算法背景周末温习了一下递归相关的一些概念,本文先给出阶乘的五种算法。第一种实现:递归1privatestaticlongRecursiveFac(longn)2{3if(n==0

大家好,又见面了,我是你们的朋友全栈君。

背景

周末温习了一下递归相关的一些概念,本文先给出阶乘的五种算法。

第一种实现:递归

 1         private static long RecursiveFac(long n)
 2         {
 3             if (n == 0)
 4             {
 5                 return 1;
 6             }
 7             else
 8             {
 9                 return n * RecursiveFac(n - 1);
10             }
11         }

第二种实现:递推

 1         private static long Fac(long n)
 2         {
 3             var result = 1;
 4 
 5             for (var i = 1; i <= n; i++)
 6             {
 7                 result = result * i;
 8             }
 9 
10             return result;
11         }

第三种实现:尾递归

1         private static int TailRecursiveFac(int n, int accumulator)
2         {
3             if (n == 0)
4             {
5                 return accumulator;
6             }
7 
8             return Fac(n - 1, n * accumulator);
9         }

第四种实现:消除尾递归

 1         private static int Fac(int n, int accumulator)
 2         {
 3             while (true)
 4             {
 5                 var tempN = n;
 6                 var tempAccumulator = accumulator;
 7 
 8                 if (tempN == 0)
 9                 {
10                     return tempAccumulator;
11                 }
12 
13                 n = tempN - 1;
14                 accumulator = tempN * tempAccumulator;
15             }
16         }

第五种实现:堆栈(堆中分配的栈)替换函数栈

 1         private enum CodeAddress
 2         {
 3             Start,
 4             AfterFirstRecursiveCall
 5         }
 6 
 7         private class StackFrame
 8         {
 9             public long N { get; set; }
10 
11             public long FirstRecursiveCallResult { get; set; }
12 
13             public CodeAddress CodeAddress { get; set; }
14         }
15 
16         private static long StackFac(long n)
17         {
18             var stack = new Stack<StackFrame>();
19             stack.Push(new StackFrame
20             {
21                 N = n,
22                 CodeAddress = CodeAddress.Start
23             });
24 
25             long result = 0;
26 
27             while (stack.Count > 0)
28             {
29                 var current = stack.Peek();
30 
31                 switch (current.CodeAddress)
32                 {
33                     case CodeAddress.Start:
34                         if (current.N == 0)
35                         {
36                             result = 1;
37                             stack.Pop();
38                         }
39                         else
40                         {
41                             current.CodeAddress = CodeAddress.AfterFirstRecursiveCall;
42                             stack.Push(new StackFrame
43                             {
44                                 N = current.N - 1,
45                                 CodeAddress = CodeAddress.Start
46                             });
47                         }
48                         break;
49                     case CodeAddress.AfterFirstRecursiveCall:
50                         current.FirstRecursiveCallResult = result;
51 
52                         result = current.N * current.FirstRecursiveCallResult;
53                         stack.Pop();
54                         break;
55                 }
56             }
57 
58             return result;
59         }

备注

这里比较有意思的实现是:尾递归和基于堆中的栈的递归,本文先不详细介绍了,后面再细说,有兴趣的朋友先看如下资源:

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/155051.html原文链接:https://javaforall.net

(0)
上一篇 2022年7月3日 下午10:36
下一篇 2022年7月3日 下午10:36


相关推荐

  • RabbitMQ使用规范「建议收藏」

    RabbitMQ使用规范「建议收藏」RabbitMQ使用规范命名exchange:{模块名}.{功能名}queue:{word}.{word}routingkey:{word}.{word},例:merge.request,原因:.之间的会被认为是一个单词,便于通过*和#来匹配一个或多个单词序列化默认情况下RabbitMQ发送的消息是为字节码,我们采用统一的JSON格式的消息使用MessageConvert自动转换为JSON如果规定了消息的格式为JSON,并使用消息转换器,则会自动将消息转化为JSON格式而不需要每次

    2022年10月3日
    6
  • STM32—中断详解(配合按键中断代码,代码亲测)

    STM32—中断详解(配合按键中断代码,代码亲测)在 STM32 中执行中断主要分三部分 1 配置 NVIC Config 函数 2 配置 EXTI Config 函数 3 编写中断服务函数 注 本文章所用代码为中断按键代码 实现了按键进入中断从而控制 LED 亮灭 配置 NVIC Config 函数 NVIC 是嵌套向量中断控制器 控制着整个芯片中断相关的功能 它跟内核紧密耦合 是内核里面的一个外设 NVIC Config 函数代码如下 s

    2026年3月19日
    2
  • java中什么是过滤器_JAVAweb过滤器

    java中什么是过滤器_JAVAweb过滤器【扩展】过滤器:Filter概念:对目标资源的请求和响应进行过滤截取。在请求到达servlet之前,进行逻辑判断,判断是否放行到servlet;也可以在一个响应response到达客户端之前进行过滤,判断是否允许返回客户端。场景:(用户授权的过滤器:判断用户是否有权限请求界面)(日志信息的过滤器:过滤用户在网站的所有请求,记录轨迹 )(负责解码的过滤器:规定请求的解码方式)备注:过滤…

    2022年8月23日
    8
  • AFL源码分析之afl-gcc.c详细注释

    AFL源码分析之afl-gcc.c详细注释前言很久之前就想拿出一块时间好好看看 AFL 不过因为一些事情耽误了 最近学习了一下 boofuzz 在协议方面的模糊测试 通过 sakura 大佬的点拨觉得还是应该静下心好好看看 AFL 的源码 写出来就当是笔记了 本文主要参考初号机大佬博客 大佬连接及 AFL 源码下载地址如下 初号机大佬链接 https bbs pediy com thread 265936 htmAFL 项目链接 https github com google AFL 编写不易 如果能够帮助到你 希望能够点赞收藏加关注哦 Thanks

    2026年3月16日
    1
  • 【报错解决办法】ModuleNotFoundError: No module named ‘numba‘[通俗易懂]

    【报错解决办法】ModuleNotFoundError: No module named ‘numba‘[通俗易懂]numba是一款可以将python函数编译为机器代码的JIT编译器,经过numba编译的python代码(仅限数组运算),其运行速度可以接近C或FORTRAN语言。python之所以慢,是因为它是靠CPython编译的,numba的作用是给python换一种编译器。numba可以基于llvm动态生成优化代码,提高python的执行效率,只需要给python代码加上修饰器就好了。如果遇到ImportError:Nomodulenamednumba这样的问题,安装nu

    2025年8月14日
    4
  • pycharm安装的基本步骤_pycharm32位怎么安装

    pycharm安装的基本步骤_pycharm32位怎么安装pycharm的安装步骤

    2022年8月27日
    10

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号