【问题标题】:Recursion to loop using a stack使用堆栈递归循环
【发布时间】:2014-12-10 22:18:19
【问题描述】:

我想使用堆栈和循环将以下程序转换为非递归代码:

void write(int n) {
    if (n>0) {
        write(n-1);
        cout << n << " ";
        write(n-1);
    }
}

这是我正在使用的代码,但目前不起作用,我不知道为什么:

stack<int> S;
S.push(n);
while (not S.empty()) {
    int k = S.top(); 
    S.pop()
    if (k>0) {
        S.push(k-1);
        cout<<k<<" ";
        S.push(k-1);
    }
}

它不起作用,我不知道如何模拟该递归。我认为将等效的递归调用推入堆栈就足够了。

谢谢

【问题讨论】:

  • 避免双重S.push(k-1);
  • 我需要两次推送,因为有 2 个记录。调用 write 函数,否则它只会写入从 n 到 1 的数字。
  • @DieterLücking 在递归中有双重调用,所以不是问题
  • @Ruben 你的假设是错误的,如果只有一个电话就等价了
  • 那怎么一通电话呢?

标签: c++ loops recursion stack


【解决方案1】:

问题是你做了 2 次推送到堆栈,但首先 write() 在所有调用链的打印之前被递归调用。

这是您的递归调用的迭代等效项:

std::stack<int> S;
for( int i = n; i > 0; --i )
   S.push( i );

while( not S.empty() ) {
    int k = S.top();
    S.pop();
    for( int i = k - 1; i > 0; --i ) {
        S.push( i );
    }
    std::cout << k << " ";
}

【讨论】:

    【解决方案2】:

    您的问题是对write(n - 1) 的第一次调用发生在输出之前,但弹出值的评估发生在它之后。

    您可以让您的堆栈模拟实际的激活记录:

    enum Action
    {
      Call, Write
    };
    
    struct Record
    {
      Action action;
      int arg;
    };
    
    stack<Record> S;
    S.push({Call, n});
    while (not S.empty()) {
      auto rec = S.top();
      S.pop()
      switch (rec.action) {
        case Call:
          if (rec.arg > 0) {
            S.push({Call, rec.arg - 1}); // corresponds to 2nd write() call
            S.push({Write, rec.arg});
            S.push({Call, rec.arg - 1}); // corresponds to 1st write() call
          }
          break;
        case Write:
          std::cout << rec.arg << ' ';
          break;
      }
    }
    

    【讨论】:

    • 所以你区分了我们什么时候必须写和什么时候必须推动?在这种情况下,您永远不会更改 Rec.arg ?
    • @Ruben 我为什么要改变它?它只是从堆栈中读取的值。这就像在原始递归函数中更改 n 的值。
    • nvm,刚刚意识到你推送的方式:p
    • 所以有一个变量表示需要做什么。如果有更多的情况,比如说 3,这个变量会有 3 个值吗?并且ofc开关会相应改变?
    • @Ruben 是的,会的。
    猜你喜欢
    • 2014-01-17
    • 2014-06-12
    • 2018-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-13
    • 1970-01-01
    • 2020-07-20
    相关资源
    最近更新 更多