算法:阶乘的五种算法

背景

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

第一种实现:递归

 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。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/547158.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TortoiseGIT创建及合并分支

一、创建分支 项目右键 > TortoiseGit(T) > 创建分支&#xff0c;然后右键切换到刚刚创建的分支&#xff0c;新增/修改一个文件&#xff0c;提交分支到远端服务器&#xff0c;推送成功之后分支就创建好了。 二、合并分支 分支开发的代码先推送到远端&#xff0c;切换本…

如何画出企业系统架构图

该技术架构图是本人根据多年企业技术架构经验而制定&#xff0c;是企业技术的总架构图&#xff0c;希望对CTO们有所借鉴。 简单说明&#xff1a; 1.中间件基础运行环境是经过统一规划的以WebLogic、JBOSS为主的集群环境 2.企业集成平台是以基础业…

ashx中Response.ContentType的常用类型

ashx中Response.ContentType的常用类型&#xff1a; text/plaintext/htmltext/xmlapplication/jsonimage/GIFapplication/x-cdf

go 语言链接服务器上的mysql数据库

2019独角兽企业重金招聘Python工程师标准>>> 在网上找了一大堆例子&#xff0c;最后简化一下把&#xff0c;一下会从安装mysql开始&#xff0c;与大家分享一下如何用go链接服务器上的mysql 我用的是ubuntu系统 1&#xff0c;安装mysql&#xff1a;sudo apt-get in…

Nginx、LVS、HAProxy 的区别和优缺点

Nginx、LVS、HAProxy 是目前使用最广泛的三种负载均衡软件&#xff0c;本人都在多个项目中实施过&#xff0c;通常会结合Keepalive做健康检查&#xff0c;实现故障转移的高可用功能。 1&#xff09;在四层&#xff08;tcp&#xff09;实现负载均衡的软件&#xff1a; lvs------…

mssql 字增自段怎样重置(重新自增)|清空表已有数据

方法1 -- 清空已有数据&#xff0c;并且将自增自段恢复从1开始计数 truncate table 表名 方法2 -- 不清空已有数据&#xff0c;但将自增自段恢复从1开始计数 dbcc checkident(表名,RESEED,0) 让SQL自动增长的ID号从一个新的位置开始在查询分析器中执行后,该表自动增长列从1开始…

Android 基本测试工具的使用

Android 基本测试工具的使用和无线学习介绍1&#xff0c;日志查看工具1&#xff09;DDMSAndroid测试中&#xff0c;使用最多的日志查看工具就是DDMS了。ddms可以从两个地方打开&#xff0c;1&#xff0c;Eclipse的的ddms插件&#xff08;属于Eclipse 的SDK插件&#xff09;&…

服务端接口中的那些坑

TOP1&#xff1a;版本意识与兼容性问题。 对于一个好的程序员来说&#xff0c;思考的时间>写代码的时间&#xff0c;如果思路不对写的代码越多&#xff0c;错的也越多&#xff0c;任何时候思考是保证高效工作最省事的武器。 对于接口开发&#xff0c;不同于bs项目&#xff…

JS逆向学习笔记

JS逆向学习笔记 寻找深圳爬虫工作&#xff0c;微信:cjh-18888 文章目录 JS逆向学习笔记 一. JS Hook 1. JS HOOK 原理和作用 原理&#xff1a;替换原来的方法. (好像写了句废话)作用&#xff1a; 可以去Hook一些内置的函数, 例如Debugger, setInterval,JSON.stringify等等2.JS…

bfs+优先队列(hdu1242)

题目&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid1242这题目就是个大坑&#xff0c;先说下思路就是在遇到‘x’时要多停留1步&#xff0c;另外就是要用到优先队列&#xff0c;要从小到大排列&#xff0c;另外就是普通的bfs了 但是要注意题里的each of Angels frien…

vscode使用汇总——常用插件、常用配置、常用快捷键

一、代码提示快捷键设置&#xff1a;&#xff08;keybindings.json&#xff09; [{"key": "ctrlj","command": "-workbench.action.togglePanel"},{"key": "ctrlj","command": "editor.action.tri…

HDFS使用JavaAPI操作上传特定副本到datanode

一、首先自然是导包 $HADOOP_HOME/share/hadoop/common/*.jar $HADOOP_HOME/share/hadoop/common/lib/*.jar $HADOOP_HOME/share/hadoop/hdfs/*.jar $HADOOP_HOME/share/hadoop/hdfs/lib/*.jar 二、代码如下 package com.stu.hdfs; /*** * author ysw28* HDFS的API操…

centos php 版本升级 至5.3 wordpress3.7

今天换了主机&#xff0c;wordpress居然出现下面的错误&#xff1a; 您的服务器现在运行的PHP版本为5.1.6&#xff0c;但WordPress 3.7要求的最低版本为5.2.4。 http://www.webtatic.com/packages/php53/ 这里已经准备了 5.3的安装包, 包括相关的扩展 升级命令&#xff1a; rpm…

vuejs深入浅出—基础篇

一、从HelloWorld说起 任何语言的都是从Hello World开始的&#xff0c;VueJs也不例外&#xff0c;直接上代码&#xff1a; <script src"https://unpkg.com/vue/dist/vue.js"></script><div id"demo">{{hello}}</div><script&g…

近百家公司高级运维的面试题汇总

10月1日日考题 画出系统应用架构图写出LVS与nginx的区别当前数据库服务处理速度慢&#xff0c;你认为可能是什么原因导致的&#xff0c;并阐述一下对应的解决办法说一下你知道的存储引擎&#xff0c;建表时如何决定表使用存储引擎单张表过大有什么缺点&#xff0c;如何解决给你…

Linux idle基础

2019独角兽企业重金招聘Python工程师标准>>> Linux系统越来越受到电脑用户的欢迎&#xff0c;于是很多人开始学习Linux时&#xff0c;学习linux&#xff0c;你可能会遇到linux内核问题&#xff0c;这里将介绍linux内核中idle知识。 1. idle是什么 简单的说idle是一…

PowerDesigner版本控制器设置权限

PowerDesigner版本控制权限之前一直在Groups里面设置&#xff0c;一直没有效果&#xff0c;原因终于找出来了&#xff0c;PowerDesigner是要对每个库单独赋权限的&#xff0c;步骤如下&#xff1a; 连接上版本控制&#xff0c;在左侧菜单 Object Browser里面&#xff0c;找到你…

IT运维面试问题总结-运维工具、开源应用(Ansible、Ceph、Docker、Apache、Nginx等)

1、简述Ansible及其优势&#xff1f; Ansible是一款极其简单的开源的自动化运维工具&#xff0c;基于Python开发&#xff0c;集合了众多运维工具(puppet, cfengine, chef, func, fabric)的优点。实现了批量系统配置&#xff0c;批量程序部署&#xff0c;批量运行命令等功能。同…

程序员进阶之路—如何独当一面

今天和大家分享一下&#xff0c;程序员如何独当一面这个话题&#xff0c;这是一个很大的话题&#xff0c;我把他分成三部分来谈&#xff1a;  一、需求转换的能力或者叫理解需求的能力&#xff1b;  二、分配时间的能力&#xff1b;  三、开发质量的问题&#xff1b; 我…

html跨浏览器兼容性问题

之前写代码没注意到&#xff0c;这次学习了。 首先 img的width和height属性在IE浏览器中不起作用&#xff0c;可以设置一个div&#xff0c;让img标签在div块中&#xff0c;div中设置style:overflow:hidden,然后用div的宽和高来定义图片的宽和高。 第二个就是&#xff0c;clear:…