算法:阶乘的五种算法

背景

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

第一种实现:递归

复制代码
 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         }
复制代码

备注

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

 

posted on   幸福框架  阅读(29000)  评论(7编辑  收藏  举报

编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
我要啦免费统计
点击右上角即可分享
微信分享提示