【问题标题】:How would one count the steps of a recursive program如何计算递归程序的步骤
【发布时间】:2016-08-27 20:15:02
【问题描述】:

我知道我需要一个程序计数器,我需要跟踪每个递归调用或步骤,这在 for 循环中很容易做到,但对于递归程序来说很难。我对如何计算所有递归步骤感到困惑。到目前为止,这就是我所拥有的。我也在考虑制作我的方法void,但使用int,我至少可以根据最后的步骤尝试return counter,但它不起作用。

int fibRec( int x, int counter )
{  
    if (x == 0)
        return  0;
    else if (x == 1)
        return 1;
    else
    {
        counter++;
        return fibRec((x - 1) + (x - 2), counter);
    }
}

【问题讨论】:

  • 呃...int &counter?
  • 保留一个全局变量怎么样
  • 你也可以去掉 counter 参数,声明一个静态 int 计数器,在编译单元内全局共享。
  • 如果这应该是斐波那契 - 最后一行有错误。它应该是两个较小的 fib 的总和: ( fibRec(x-1) + fibRec(x-2) )
  • @DOUGLASO.MOEN 哈哈,谢谢,但我知道,我只是在尝试一些新的东西。

标签: c++ recursion


【解决方案1】:

这在 for 循环中很容易做到,但对于递归程序来说却很难

抱歉,你错了——在 C++ 中为递归程序添加计数器等是微不足道的。

a) 请注意,不需要全局。
b) 不需要额外的方法参数。

像往常一样,C++ 的解决方案是创建一个类

作为类的一部分的非静态递归方法将始终具有 this 指针,因此可以访问该类的任何部分,包括您可能需要的任意数量的添加计数器和报告或方法。

这是一种可能的方法:

class FibRec
{
public:
   FibRec() : counter(0) {
      std::cout << "FibRec ctor " << counter << std::endl;
   };

   ~FibRec() { // output final value with dtor
      std::cout << "FibRec dtor " << counter << std::endl;
   };

   int exec( int x )
      {
         if (x == 0)       return  0;
         else if (x == 1)  return 1;
         else
         {
            counter++;
            // dbg: std::cout << counter << "  " <<  x << std::endl;

            return (exec(x - 1) + exec(x - 2)); 
            // note -- Fibonacci fix?
         }
      }
private:
   int counter;
};


int t407(void)
{
   FibRec f;   // class instance
   f.exec(5);  // invoke recursive method

   return(0);
}

注意:使用 g++ 的 ubuntu 15.10 上的默认堆栈大小为 8 MB。这是很多递归。

不幸的是,您的代码有一个错误 - 它“添加”并很快增长到溢出。当计数器为 272,261 时,我的代码显示溢出。您需要修复代码。

我猜这段代码应该是斐波那契,它是两个中间值的总和。不是你编码的。

您可以通过更改以下代码来实现您想要的:

return fibRec((x - 1) + (x - 2), counter);

到:

return (fibRec(x - 1, counter) + fibRec(x - 2, counter));

祝你好运。

【讨论】:

  • 这就是程序的精髓,说明计算第n个斐波那契数需要多少步。根据我的算法,我得到了前 30 个斐波那契数列的 2178278 步。
  • 另外你的方法看起来很高级,我刚刚开始,对你来说可能很简单的事情对我来说很难。但我喜欢你的意见,以后我会接受你所说的。我最终将counter 声明为main 的全局变量,并在fib() 方法中递增,这样我就可以访问counter 以在main 中进行输出。感谢您的意见。
【解决方案2】:

您需要传递 counter 作为参考:

int fibRec( int x, int &counter )

这样,传入的调用者的局部变量就会被更新。此外,您可能需要考虑为基本情况(0 和 1)增加 counter,因为它们在技术上也是步骤。

【讨论】:

  • 值得注意的缺点是:除非编译器做了一些很酷的事情,否则每次调用使用的内存会增加一倍或三倍。您将更快地耗尽存储空间。
  • 感谢增加基本情况,但我最终将 counter 声明为 main 方法的全局,并仅在递归 fibonnaci 方法中使用它。这样,一旦fib() 完成,我就可以在 main 中打印计数器值。再次感谢。
【解决方案3】:

你可以传递一个变量作为参考

void fibRec( int x, int &counter )

或者你可以像下面的代码一样声明一个全局变量计数器

int counter = 0;
int fibRec( int x )
{  
    if (x == 0)
        return  0;
    else if (x == 1)
        return 1;
    else
    {
        counter++;
        return fibRec((x - 1) + (x - 2));
    }
}

【讨论】:

猜你喜欢
  • 2013-06-08
  • 2016-07-22
  • 1970-01-01
  • 2012-12-08
  • 2021-11-12
  • 1970-01-01
  • 2014-04-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多