【问题标题】:Changing this from recursion to iteration将其从递归更改为迭代
【发布时间】:2013-04-15 13:37:04
【问题描述】:

一些伪代码:

 func F(int x. int y, array p){
       p[x] = 1;
       if (x<=y){
          for each item in getItems(x,p){
              p = F(item,y,p);
          }
       }
       return p;
    }

getItems() 返回一个基于 x 和 p 的数字数组,对于这个问题并不重要,但它会返回一些高于和低于 x 的数字。然而,这意味着如果 x 太大,那么我会炸毁递归堆栈,因为它会深入到 x 之下。

如何将其更改为迭代?

【问题讨论】:

  • 因为它是你的程序将进入无限循环(如果你使用递归或迭代无关紧要)。先搞清楚逻辑。
  • 它不会进入无限循环。它适用于较小的范围。问题是边界太大。
  • 请显示getItems的简化版。它如何依赖于p
  • 一个愚蠢的问题:你是按值传递和返回数组吗?
  • 没关系;它只返回 x 以下的几个数字和 x 以上的几个数字,基于 p 的哪些元素已经被标记(这与质数有关,所以如果这就是你问的原因,这里没有很好的模式。这不是简单的 clean 函数,但重写 F) nm: 否,通过引用不需要它

标签: algorithm recursion iteration


【解决方案1】:

您可以通过添加一个防止您重复处理 x 值的保护来保留递归版本(没有堆栈溢出)

func F(int x. int y, array p){
   if(p[x] != 1) {
       p[x] = 1;
       if (x<=y){
           for each item in getItems(x,p){
               p = F(item,y,p);
          }
       }
   }
   return p;
}

如果您的某些数组值可能已初始化为 1,则将其更改为类似

if(p[x] != null) {
    p[x] = null;

即分配一个您知道未在初始数组中使用的值。然后当函数完成其处理时,遍历数组并将所有空值设置为 1。

【讨论】:

    【解决方案2】:

    您可以通过模拟调用堆栈来做到这一点:

    struct stackentry {
        int x;
        Item item; // see exercise for reader, below
    };
    
    func F(int x, int y, array p){
       dynamic_list_of_stackentry mystack;
      start:
       p[x] = 1;
       if (x<=y){
          for each item in getItems(x,p){
              mystack.push(stackentry(x, item));
              x = item
              goto start
            resume:
              x = mystack.top().x;
              item = mystack.top().item;
              mystack.pop();
          }
       }
       if mystack.size() > 0:
          goto resume
       return p;
    }
    

    留作练习:更改迭代,以便您可以将当前迭代的集合(来自getItems())和您在其中的当前位置存储为堆栈条目的一部分。

    我并不是说这是优雅的代码,但是您可以从一个与您的递归函数相同的非递归函数的起点开始重构。例如,您的下一步可能是:

    func F(int x, int y, array p){
       dynamic_list_of_int mystack;
       mystack.push(x)
       while not mystack.empty() {
           x = mystack.top();
           mystack.pop();
           p[x] = 1;
           if (x <= y) {
               for each item in reversed(getItems(x,p)) {
                   mystack.push(item);
               }
           }
       }
       return p;
    }
    

    【讨论】:

      猜你喜欢
      • 2019-03-01
      • 2010-10-06
      • 2015-04-23
      • 2015-03-14
      • 1970-01-01
      • 1970-01-01
      • 2020-12-23
      • 2021-03-07
      相关资源
      最近更新 更多