算法:阶乘的五种算法

算法:阶乘的五种算法背景周末温习了一下递归相关的一些概念,本文先给出阶乘的五种算法。第一种实现:递归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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • python unicode编码转换utf-8编码_不成问题的问题人物解析

    python unicode编码转换utf-8编码_不成问题的问题人物解析Unicode也叫万国码、单一码,是计算机科学领域里的一项业界标准,包括字符集、编码方案等。对于世界上所有的语言文字再unicode中都可以查看到。【汉】字的编码解释官网https://www.unicode.org/cgi-bin/GetUnihanData.pl?codepoint=6C49unicode编码就是为了统一世界上的编码,有一个统一的规范。但是它还存在一些问题。Unicode的问题需要注意的是,Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存

    2022年9月30日
    4
  • perl正则表达式匹配后的各种变量

    perl正则表达式匹配后的各种变量[root@rwsoda203db1perl_tidb]#catp.pl#!/usr/bin/perlusestrict”subs”;usestrict;usev5.16;my$n=3;my$str=”first.<EM>PARENT</EM>LAST”;$str=~m#(<.*?>)(.*?)(</….

    2022年5月6日
    42
  • 无需插件只使用浏览器下载b站视频

    无需插件只使用浏览器下载b站视频2017.10.07更新:由于现在bilibili更改了refer的Host并使用了防盗链,原文的方法直接下载会有403错误,在博主琢磨出新的抓包方法之前可以先使用以下的方法:在bilibili网址前加上kan,然后回车,加载出来的东西应该就很直白了。例子:地址栏中的https://www.bilibili.com/video/av11175437/加上kan以后变成https:

    2022年7月12日
    24
  • JVM内存模型(通俗易懂)

    JVM内存模型(通俗易懂)1.什么是jvm?(1)jvm是一种用于计算设备的规范,它是一个虚构出来的机器,是通过在实际的计算机上仿真模拟各种功能实现的。(2)jvm包含一套字节码指令集,一组寄存器,一个栈,一个垃圾回收堆和一个存储方法域。(3)JVM屏蔽了与具体操作系统平台相关的信息,使Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。JVM在执行字节码时,实际上最终还是把字节码解释成具体平台上的机器指令执行。2.jdk、jre、jvm是什么关系?(1)JRE(JavaR

    2022年4月28日
    78
  • flash视频器播放器代码

    flash视频器播放器代码flash视频器播放器代码代码整理:

    2022年7月3日
    21
  • CSDN Chrome插件来了。助开发者提升开发效率,远离996

    插件定位帮助开发者提升开发效率,远离996特点以搜索框为入口,集成开发者常用工具,提升开发效率主要功能如下:支持本地书签、tab页、历史记录搜索集成CSDN搜索结果,本地内容和远程结果无缝集成所有操作都支持快捷键,提升搜索效率他是一个时间转换工具他是一个计算器他是。。。,更多功能正在添加中安装下载安装包浏览器输入地址“chrome://extensions/”进入扩展程序页面,开启开发者模式以下操作任选其一:zip文件安装:点击“加载已解压的扩展程序”按钮,选择已解压

    2022年4月8日
    62

发表回复

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

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