递归——CPS(三)

JScript不是天然支持CPS,但是可以写一个分发引擎使得能工作在CPS风格下。一般只有一个活动的continuation,所以可以定义规则:JScript CPS 函数允许有返回,但是它们做的最后一件事必须是将continuation告诉我们的分发引擎。

为了让事情简单化,我们令每个CPS 风格的函数拥有一个参数,当然,可以是一个包含多个字段的对象。

让我们回顾一下前面的 CPS treeDepth程序,并且将所有的 continuation 调用 替换为 这样一种调用: 这种调用告诉运行时引擎下一步 continuation 该做什么。然后,函数可以正常返回,并且让运行时引擎调用continuation。

function treeDepth(args)
{
    if(args.curtree == null)
        cont(args.afterDepth, 0);
    else
    {
        function afterLeft(leftDepth)
        {
            function afterRight(rightDepth)
            {
                cont(args.afterDepth, 1+Math.max(leftDepth, rightDepth));
            }
            cont(treeDepth, {curtree: args.curtree.right, afterDepth: afterRight});
        }
        cont(treeDepth, {curtree: args.curtree.left, afterDepth: afterLeft});
    }
}

分发引擎为

var continuation = null;
function cont(newfunc, newargs)
{
    continuation = {func: newfunc, args : newargs};
}

function run()
{
    while(continuation != null)
    {
        var curfunc = continuation.func;
        var curargs = continuation.args;
        continuation = null;
        curfunc(curargs);
    }
}

如果下一步没有需要调用的话,就表示程序完成。为了确定一棵树的深度,我们简单地告诉continuation引擎下一步需要做什么。

cont(treeDepth, {curtree: mytree, afterDepth: print });
run();

原文:https://blogs.msdn.microsoft.com/ericlippert/2005/08/15/recursion-part-six-making-cps-work/

时间: 2024-10-05 23:47:38

递归——CPS(三)的相关文章

递归——CPS(一)

程序中为什么需要栈stack? 普通的程序中,接触到子程序和函数的概念,很直观地,调用子程序时,会首先停止当前做的事情,转而执行被调用的子程序,等子程序执行完成后,再捡起之前挂起的程序,这有可能会使用刚才子程序计算出的数据.但是在程序被挂起的地方重新捡起程序并继续执行需要一个机制,即,存储当前所做事情的相关信息和以后在哪里捡起这个程序(现场信息).这时,栈自然而然就是满足这种需要的一个数据结构(为什么使用栈略过不提). 如果情况发生改变,没有函数需要返回,函数要么终止程序,要么是调用另一个函数,

递归——CPS(二)

给出一个计算树深度的函数: function treeDepth(curtree) { if(curtree == null) return 0; else { var leftDepth = treeDepth(curtree.left); var rightDepth = treeDepth(curtree.right); return 1 + Math.max(leftDepth, rightDepth); } } 现在要用CPS风格重写这个函数. 避免函数的返回值,而是将返回值传入con

Binary Tree Inorder Traversal [leetcode] 非递归的三种解法

第一种方法是Morris Traversal 是O(n)时间复杂度,且不需要额外空间的方法.缺点是需要修改树. 通过将叶子节点的right指向其中序后继. 代码如下 vector<int> inorderTraversal(TreeNode *root) { vector<int> res; TreeNode * cur = root; TreeNode * pre = NULL; while (cur) { if (cur->left == NULL) { res.push

二叉树的存储方式以及递归和非递归的三种遍历方式

树的定义和基本术语 树(Tree)是n(n>=0)个结点的有限集T,T为空时称为空树,否则它满足如下两个条件: (1)有且仅有一个特定的称为根(Root)的结点: (2)其余的结点可分为m(m>=0)个互不相交的子集T1,T2,T3-Tm,其中每个子集又是一棵树,并称其为子树(Subtree). 树形结构应用实例: 1.日常生活:家族谱.行政组织结构:书的目录 2.计算机:资源管理器的文件夹: 编译程序:用树表示源程序的语法结构: 数据库系统:用树组织信息: 分析算法:用树来描述其执行过程:

递归(三):排列

排列组合是组合学最基本的概念.所谓排列,就是指从给定个数的元素中取出指定个数的元素进行排序.组合则是指从给定个数的元素中仅仅取出指定个数的元素,不考虑排序. 排列与组合在日常生活中应用较广,比如在考虑某些事物在某种情况下出现的次数时,往往需要用到排列和组合. [例1]n位二进制数的全排列. 编写一个程序,输入一个自然数n(1<=n<=10),输出n位二进制数的全排列.例如,输入3,输出8个3位二进制数的序列:000.001.010.011.100.101.110.111. (1)编程思路. 可

PHP实现递归的三种方法

递归函数是我们常用到的一类函数,最基本的特点是函数自身调用自身,但必须在调用自身前有条件判断,否则无限无限调用下去.实现递归函数可以采取什么方式呢?本文列出了三种基本方式.理解其原来需要一定的基础知识水品,包括对全局变量,引用,静态变量的理解,也需对他们的作用范围有所理解.递归函数也是解决无限级分类的一个很好地技巧. 利用引用做参数 先不管引用做不做参数,必须先明白引用到底是什么?引用不过是指两个不同名的变量指向同一块存储地址.本来每个变量有各自的存储地址,赋值删除各行其道.现在可好,两个变量共

递归 2008 三2 双语版

素数递归统计三项代码

        public static void isprime() {             int n;import java.util.Scanner; public class number {     public static void main(String[] args) {             int i = 0;             System.out.println("1.3-100 2.任意两数 3.最大十个和最小十个");           

递归程序如何写,要满足三个条件,切记!

python中递归函数的使用: def division(n): print(n) if int(n/2)==0: return n#递归特性一:必须有一个明确的结束条件 return division(int(n/2))#递归特性而:每次递归都是为了让问题规模变小 division(10)#递归特性三:递归层次过多会导致栈溢出,且效率不高--------------------- 作者:贾公子 来源:CSDN 原文:https://blog.csdn.net/j904538808/articl