【问题标题】:Keeping count in non-tail recursion在非尾递归中保持计数
【发布时间】:2017-06-24 06:21:46
【问题描述】:

我正在用函数式语言 (ML) 编写几个递归函数,其中一些函数需要保持计数。我不允许使用尾递归或辅助函数。我应该如何计数?

例如,如果一个问题要求我删除字符串的第 n 个元素,我怎么知道递归函数在删除该元素之前已经被调用了 n 次?

【问题讨论】:

    标签: recursion count ml


    【解决方案1】:

    您可以将计数作为参数传递。我不了解 ML,但在 C 风格的语言中,它是这样完成的:

    void processTreeNode(Node* node, int count) {
    
        foreach(Node* child in node->children) {
            processTreeNode( child, count + 1 );
        }
    }
    

    第一次调用的值通常为01

    Node* root = ...
    processTreeNode( root, 1 );
    

    请注意,上面的示例实际上计算的是 depth 而不是迭代次数。

    如果你想计算函数实际被调用的次数,你可以使用全局状态的值(一个坏主意)或通过引用传递的线程局部值:

    void processTreeNode(Node* node, int* count) {
    
        (*count)++;
    
        foreach(Node* child in node->children) {
            processTreeNode( child, count );
        }
    }
    

    第一个调用负责创建值和引用:

    Node* root = ...
    int   count = 0;
    processTreeNode( root, &count );
    

    这可以概括为传递给所有函数调用的算法“上下文”对象——如果它是通过引用传递的,那么这可以避免不必要的值复制和堆栈空间分配,并且在没有其他条件的情况下是线程安全的线程可以访问它:

    class MyAlgorithmContext {
        int foo;
        string bar;
    }
    
    Node* root = ...
    MyAlgorithmContext context;
    context.foo = 123;
    processTreeNode( root, &context );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-30
      相关资源
      最近更新 更多