算法:阶乘的五种算法
背景
周末温习了一下递归相关的一些概念,本文先给出阶乘的五种算法。
第一种实现:递归
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 }
备注
这里比较有意思的实现是:尾递归和基于堆中的栈的递归,本文先不详细介绍了,后面再细说,有兴趣的朋友先看如下资源:
- Replacing Recursion With a Stack。
- How to replace recursive functions using stack and while-loop to avoid the stack-overflow。
- HOW TO CONVERT A RECURSIVE ALGORITHM TO A NON-RECURSIVE ONE。
- Replace Recursion with Iteration。
- Provide an explanation of recursion, including an example。
- Tail Recursion。
- Understanding Tail Recursion。
算法:阶乘的五种算法相关推荐
- Java代码实现负载均衡五种算法
前言: 负载均衡是为了解决并发情况下,多个请求访问,把请求通过提前约定好的规则转发给各个server.其中有好几个种经典的算法.在用java代码编写这几种算法之前,先来了解一下负载均衡这个概念. 1. ...
- 三维点云学习(2)五种算法比较
三维点云学习(2)五种算法比较 代码参考来自 黎老师github 本次测试包含五种算法比较: octree print("octree --------------")#时间统计c ...
- 路径规划五种算法简述及对比
以下是本人在学习路径规划过程中的一些总结,借着机会写了一下,有不妥之处欢迎批评指正,谢谢. 路径规划部分在无人车架构体系当中分属控制或决策部分,如图1,是实现无人化驾驶的关键技术之一.路径规划模块性能 ...
- lfu算法实现java_LFU五种实现方式,从简单到复杂
前言 最近刷力扣题,对于我这种 0 基础来说,真的是脑壳疼啊.这个月我估计都是中等和困难题,没有简单题了. 幸好,力扣上有各种大牛给写题解.看着他们行云流水的代码,真的是羡慕不已.让我印象最深刻的就是 ...
- 算法简介、7种算法分类
一.算法 算法是以函数模板的形式实现的.常用的算法涉及到比较.交换.查找.搜索.复制.修改.移除.反转.排序.合并等等. 算法并非容器类型的成员函数,而是一些全局函数,要与迭代器一起搭配使用. 算法的 ...
- 数据结构和算法之常用 10 种算法
目录 1.二分查找算法(非递归) 2.分治算法 2.1分治算法最佳实践-汉诺塔 3.动态规划算法 4.KMP 算法 4.1KMP 算法最佳应用-字符串匹配问题 5.贪心算法 5.1贪心算法最佳应用-集 ...
- 自动驾驶系列(二) - 路径规划五种算法简述及对比
- 语言高精度算法阶乘_JavaScript中的算法(附10道面试常见算法题解决方法和思路)...
https://juejin.im/post/6844903811505455118 Introduction 面试过程通常从最初的电话面试开始,然后是现场面试,检查编程技能和文化契合度.几乎毫无例外 ...
- Python算法练习(五)// 算法:KMeans,数据集:标准普尔500指数
本练习利用KMeans算法对标准普尔500指数的股票进行聚类,为进一步投资提供决策参考.该数据集有2个特征,借助散点图明显看出股票可以分为4类.建立模型后,通过肘部法和轮廓系数得到最佳的簇数为4.最后 ...
最新文章
- linux下git的简单使用
- python正则group()的用法—正则提取括号内以及其他符号内内容
- C语言打印九九乘法口诀
- 【jzoj】2018.1.31 NOIP普及组——D组模拟赛
- NOIP2011 铺地毯
- 传统手工特征--opencv
- 李佳琦“云逛”进博会 携手央视带货阿富汗松子
- c语言制作图片软件,大佬们,小菜鸟想问一问用vc编译器做简易画图软件
- 静态函数 静态变量和常量
- 『ORACLE』 DG性能转换(11g)
- 【直接下载】x86_64-6.3.0-release-win32-seh-rt_v5-rev2
- excel导入,用反射匹配字段名
- 常见的HTPP状态码
- python如何拼读英语单词怎么写_浅谈如何拼读英语新单词
- 基于android的lbs技术,基于Android的LBS系统研究
- Ubuntu开发嵌入式串口权限问题
- R语言读取文件报错之二:Error in read.table(“xxxx.txt“, header = TRUE) : 列的数目比列的名字要多
- 【数据处理】格式化数据
- Netty源码实战(十) - 性能优化
- shell卸载 simatic_Siemens Simatic WinCC v7.5 SP1 (x64)ISO 授权安装教程
热门文章
- python 数据流中的移动平均值_剑指Offer-41-数据流中的中位数
- pandas 每一列相加_Python3 numpy amp; pandas 学习笔记
- php如何实现购物时数量增减,1、vuex状态管理--购物车数量增减
- python字符串出栈方法_1.Python实现字符串反转的几种方法
- springboot中接口实例化_AngularJs中控制器的定义,实例化,作用域范围
- C语言、C++学习路线
- document.getElementById()与 $()区别
- idea for循环快捷键_IDEA骚技巧,编码速度至少快一倍
- checkbox wpf 改变框的大小_【论文阅读】倾斜目标范围框(标注)的终极方案
- php访问js文件不存在,php文件里js不能被执行