• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C#教程 > C#中的递归APS和CPS模式详解

C#中的递归APS和CPS模式详解

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了aps,莱茵春天aps,aps铝型材,德国aps项目,钉钉 aps安装包等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

累加器传递模式(Accumulator passing style)

尾递归优化在于使堆栈可以不用保存上一次的返回地址/状态值,从而把递归函数当成一个普通的函数调用。

递归实际上是依赖上次的值,去求下次的值。 如果我们能把上次的值保存起来,在下次调用时传入,而不直接引用函数返回的值。 从而使堆栈释放,也就达到了尾递归优化的目的。

下面我们增加了一个acc的参数,它存储上次的值,在下次调用时传入。
static int Accumulate(int acc, int n)
    {
        if (n == 0)
            return acc;
        return accumulate(acc * n, n - 1);
    }
</div>

使用时Accumulate递归时,我们仅需要使用最后一次的返回值即可。 调用如下:
 var ac = Accumulate(1, 20); 
</div>
使用Lambda表达式实现尾递归阶乘:
static int AccumulateByLambda(int x)
    {
        Func<int, int, int> accumulate = null;
        accumulate = (acc, n) => n == 0 ? acc : Accumulate(acc * n, n - 1);
        return accumulate(1, x);
    }
</div>

CPS函数

CPS全称Continuation passing style,中文一般译为后继传递模式。
 static int Times3(int x)
    {
        return x * 3;
    }
   Console.WriteLine(Times3(5));
</div>
上面函数将输入值乘以3,我们平常基本上都会这样写。 其实我们还可以用返回函数的C#语法,构造嵌套方式,把函数的调用变成调用链times3(3)(5)。

这种方式在数学上或函数式编程中是比较直观的,正常的,但在指令式语言c#中却不是那么直观。

CPS中的后继(Continuation)一词指的是计算的剩余部分,类似times3(3)(5)红色这部分。
例如:表达式a*(b+c)的运算过程有多个计算步骤。可以c#写成下面函数来表示:
Console.WriteLine(Mult(a,Add(b,c)))
</div>

操作步骤如下:

1.b与c相加。
2.将结果乘以a。
3.输出结果。

执行1步时,后续操作是2,3。执行2步时,后续操作是3。 使用CPS模式来改造下times3函数:
static void Times3CPS(int x, Action<int> continuation)
    {
        continuation(x * 3);
    }
Times3CPS(5, (reslut) => Console.WriteLine(result));
</div>
我们增加了一个表示后继操作3的函数参数,调用时传递后续操作,这就是CPS函数。

CPS变换

知道了CPS函数后,再详细看下CPS变换。
Console.WriteLine(Times3(5));
//CPS变换
Times3CPS(5, (reslut) => Console.WriteLine(result));
</div>
上面times3函数从直接调,到使用"后继传递操作"的过程就叫做CPS转换。
例如1:MAX函数的转换
static int Max(int n, int m)
{
    if (n > m)
        return n;
    else
        return m;
}
 Console.WriteLine(Max(3, 4));
</div>

我们把这max函数转换成CPS模式,需要下列步骤:
1:返回值修改成void
2:添加一个额外的类型参数 Action,T是原始返回类型。
3:使用后续操作表达式参数替代原来所有返回声明。

static void Max(int n, int m, Action<int> k)
{
    if (n > m)
        k(n);
    else
        k(m);
}
Max(3, 4, x => Console.WriteLine(x));
</div>

例如2:假如有3个函数Main、F、G,Main调用F、F调用G。

Console.WriteLine(F(1) + 1);
static int F(int n)
{
    return G(n + 1) + 1;
}
static int G(int n)
{
    return n + 1;
}
</div>

我们把F和G转换成CPS风格,和Max函数同样的转换步骤:
F(1, x => Console.WriteLine(x + 1));
static void F(int n, Action<int> k)
{
    G(n + 1, x => k(x + 1));
}
static void G(int n, Action<int> k)
{
    k(n + 1);
}
</div>

CPS尾递归

这是传统的递归阶乘:
static int Factorial(int n)
{
    if (n == 0)
        return 1;
    else
        return n * Factorial(n - 1);
}
</div>

使用同样的步骤,把递归转换成CPS尾递归:
Factorial(5, x => Console.WriteLine(x));
static void Factorial(int n, Action<int> continuation)
{
    if (n == 0)
 

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • C#中的递归APS和CPS模式详解
  • C# 使用匿名函数解决EventHandler参数传递的难题

相关文章

  • 2017-05-28C# IDE VS2005中的Hosting Process (vshost.exe)作用介绍
  • 2017-05-28C#编程自学之开篇介绍
  • 2017-05-28C#飞行棋小程序设计分析
  • 2017-05-28C#将Json解析成DateTable的方法
  • 2017-05-28C#通过接口与线程通信(捕获线程状态)示例代码
  • 2017-05-28C#获取路径的几种方式实例分析
  • 2017-05-28silverlight实现图片局部放大效果的方法
  • 2017-05-28C#实现winform自动关闭MessageBox对话框的方法
  • 2017-05-28详解C# 托管资源和非托管资源
  • 2017-05-28c#完美截断字符串代码(中文+非中文)

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • C#程序最小化到托盘图标操作步骤与实现代码
    • c#实现用SQL池,多线程定时批量执行SQL语句的方法
    • C#中实现Fluent Interface的三种方法
    • C#访问PostGreSQL数据库的方法
    • 基于C#的电视台节目表接口调用代码
    • C#中实现输入汉字获取其拼音(汉字转拼音)的2种方法
    • C# 实现QQ式截图功能实例代码
    • C#冒泡法排序算法实例分析
    • C#警惕匿名方法造成的变量共享实例分析
    • C#记录消息到日志文件的方法

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有