【问题标题】:variable nested for loops嵌套for循环的变量
【发布时间】:2012-03-04 14:55:33
【问题描述】:

我试图弄清楚如何使用递归来执行 n 级嵌套 for 循环。 例如,如果 n=3,则将有 3 个“级别”

for(z=0;z<6;z++){
   for(y=0;y<6;y++){
      for(x=0;x<6;x++){
         if (z+y+x==f){
            //do something
         } 
      }
   }
}

等等。

我似乎无法弄清楚如何将 if 循环放在最后一个 for 循环中,以及如何从 if 语句中访问前一个 for 循环的变量。我知道变量嵌套循环的问题已经被问过很多次了,我已经看过所有这些了。但似乎没有人能帮助我。

是否有人可以提供一种使用递归来实现这一目标的简单方法,记住我仍然是 c++ 的初学者,为我指明正确的方向?

用例如下:

编写一个程序来输入骰子的个数m。程序将输出可能案例的总数、每个可能的 n 的可能案例数量以及概率最高的 n。注意:只读入一个输入m。n由程序计算

例如如果用户输入 m=2 那么程序应该输出

可能的病例总数为 36。
可能性是
2 1
3 2
4 3
.
.
.
12 1

【问题讨论】:

  • 第二个循环中的错字?
  • 你想达到什么目的?为什么要使用递归?
  • 我只是想知道如何通过递归来实现。
  • VJovic 所说的。目前尚不清楚您要做什么。将其拆分为递归函数调用似乎没有目标。我们需要更多地了解您希望它的外观。 “递归”太模糊了。此外,没有“if循环”之类的东西
  • 我不需要递归来解决这个问题。我想尝试一种不同的方法来解决问题,因此向社区寻求帮助。

标签: c++ for-loop nested


【解决方案1】:

我今天早些时候遇到了这个问题,我想我可能会分享我最终想出的解决方案。我不确定这里关于回复旧帖子的政策是什么。我只是在今天早上遇到这个问题的事实,这种事情对我很有用。

为了提高效率,我避免了递归。此外,它不使用任何特定的 c++ 东西——它也可以在 C 上正常工作。

我们正在尝试创建 N 个嵌套的“for”循环。 而不是使用

for(int i = 0; i<max; i++)
  for (int j = 0; j<max; j++)
    ...

我将 i, j, ... 替换为一个数组:i[0], i[1], ..., i[n-1]。

这是我的解决方案:

const int n = /*Insert N here: how many loops do you need?*/;
int i[n+1]; // if "n" is not known before hand, then this array will need to be created dynamically.
//Note: there is an extra element at the end of the array, in order to keep track of whether to exit the array.

for (int a=0; a<n+1; a++) {
  i[a]=0;
}

int MAX = 79; //That's just an example, if all of the loops are identical: e.g. "for(int i=0; i<79; i++)". If the value of MAX changes for each loop, then make MAX an array instead: (new) int MAX [n]; MAX[0]=10; MAX[1]=20;...;MAX[n-1]=whatever.

int p = 0; //Used to increment all of the indicies correctly, at the end of each loop.
while (i[n]==0) {//Remember, you're only using indicies i[0], ..., i[n-1]. The (n+1)th index, i[n], is just to check whether to the nested loop stuff has finished.

  //DO STUFF HERE. Pretend you're inside your nested for loops. The more usual i,j,k,... have been replaced here with i[0], i[1], ..., i[n-1].


  //Now, after you've done your stuff, we need to increment all of the indicies correctly.
  i[0]++;
  // p = 0;//Commented out, because it's replaced by a more efficient alternative below.
  while(i[p]==MAX) {//(or "MAX[p]" if each "for" loop is different. Note that from an English point of view, this is more like "if(i[p]==MAX". (Initially i[0]) If this is true, then i[p] is reset to 0, and i[p+1] is incremented.
    i[p]=0;
    i[++p]++; //increase p by 1, and increase the next (p+1)th index
    if(i[p]!=MAX)
      p=0;//Alternatively, "p=0" can be inserted above (currently commented-out). This one's more efficient though, since it only resets p when it actually needs to be reset!
  }
}

就这些了。希望 cmets 清楚地表明它的目的是什么。我认为它应该非常有效 - 几乎与真正的嵌套 for 循环一样多。大部分开销在一开始都是一次性的,所以这应该比使用递归函数等更有效(如果我在这一点上错了,请纠正我)。

希望有一天它对某人有用。

和平与爱。

【讨论】:

  • 代码没问题,不过去掉大部分cmet会更好看。
  • 避免堆栈溢出的好主意
  • 我只发现了一种特殊情况 MAX=1,它似乎永远运行。
  • @Valentas 我添加了 'if(i[n]>0) break;' 'i[++p]++;'之后修复 MAX=1 错误。它似乎有效。
【解决方案2】:

多循环递归算法的基本结构如下:

void recursiveLoops(vector<int>& indexes, const vector<int>& endPerIndex, int currentIndex) {
    if (currentIndex == indexes.size()) {
        // This is where the real logic goes.
        // indexes[i] contain the value of the i-th index.
    } else {
        for (indexes[pos] = 0 ; indexes[pos] != endPerIndex[pos] ; indexes[pos]++) {
            // Recurse for the next level
            recursiveLoops(indexes, endPerIndex, pos+1);
        }
    }
}

从顶层调用recursiveLoops 的设置需要两个向量——一个用于索引,一个用于每个级别的迭代次数。下面的示例设置了三个嵌套循环,在每个级别迭代 5、6 和 9 次:

vector<int> indexes(3, 0);
vector<int> endPerIndex;
endPerIndex.push_back(5);
endPerIndex.push_back(6);
endPerIndex.push_back(9);
recursiveLoops(indexes, endPerIndex, 0);

【讨论】:

  • 递归函数的一个典型问题是堆栈溢出。对于变量级别的嵌套 for 循环,这很可能会发生。我知道我们的供应商将他们的循环硬编码为 5 的最大嵌套级别,他们说他们会将限制提高到 9。三年过去了,他们仍然没有这样做,哈哈。
【解决方案3】:

这是一个简单的旧 C++ 示例。首先,我为每个维度创建一个范围向量,称为maxes。如果所有索引的总和为 2,那么我 print 做了一些事情。 在示例中,我将 z 从 0 循环到 1,y 从 0 循环到 2,x 从 0 循环到 3

你肯定可以让它更整洁。

这里是:

#include <iostream>
#include <vector>
using namespace std;

int f(){ 
    return 2 ;
}

void inner(int depth,vector<int> & numbers,vector<int> & maxes){
  if (depth>0){
     for(int i=0;i<maxes[depth-1];i++){
        numbers[depth-1]=i;
        inner(depth-1, numbers,maxes) ;
     }
  }else{
     // calculate sum of x,y,z:
     cout << "values are ";
     for(int i=0;i<numbers.size();i++){
        cout <<numbers[i]<<" ";
     }
     int thesum(0);
     for(int i=0;i<numbers.size();i++){
        thesum+=numbers[i];
     }
     if (thesum==f()){
        cout << "did something! ";
     }
     cout<<endl;
   }
}

void donest(){
   vector<int>  numbers;
   numbers.resize(3);
   vector<int>  maxes;
   maxes.push_back(4);
   maxes.push_back(3);
   maxes.push_back(2);
   inner(numbers.size(),numbers,maxes);
}

int main(){
   donest();
}

结果:

values are 0 0 0 
values are 1 0 0 
values are 2 0 0  did something! 
values are 3 0 0 
values are 0 1 0 
values are 1 1 0  did something! 
values are 2 1 0 
values are 3 1 0 
values are 0 2 0  did something! 
values are 1 2 0 
values are 2 2 0 
values are 3 2 0 
values are 0 0 1 
values are 1 0 1  did something! 
values are 2 0 1 
values are 3 0 1 
values are 0 1 1  did something! 
values are 1 1 1 
values are 2 1 1 
values are 3 1 1 
values are 0 2 1 
values are 1 2 1 
values are 2 2 1 
values are 3 2 1 

【讨论】:

    【解决方案4】:

    只计算每个递归函数的深度,并数到f..

    void myRecursiveFunc(int depth){
       if(depth == f)
          //do something
          return;
       else{
          myRecursiveFunc(depth + 1);
       }
    }
    

    如果你真的想要,你可以为 x、y 和 z 使用三个不同的函数。

    【讨论】:

    • 好吧,@Lightness。我的问题如下。
    【解决方案5】:

    你对你为什么想要这个非常模糊。对于初学者来说,一个可能的解决方案是用递归函数替换每个 for 循环。

    void recursiveX(int zVal, int yVal, int xVal)
    {
        if(zVal+yVal+xVal == f)...
        if(xVal != 0)
            recursiveX(zVal, yVal, xVal -1);
    }
    
    void recursiveY(int zVal, int yVal)
    {
        recursiveX(zVal, yVal, 6);
        if(yVal != 0)
            recursiveY(zVal, yVal-1);
    }
    
    void recursiveZ(int val)
    {
        recursiveY(val, 6);
        if(val != 0)
            recursiveZ(val-1);
    }
    ...
    recursiveZ(6);
    

    最后你可以将这一切合并到一个函数中。然而,仅仅因为可能而使用递归绝不是一个好主意。

    【讨论】:

      【解决方案6】:

      你可以这样写,但是……我不会。这是令人困惑的代码,不会给您带来任何好处。如果您想要它,因为您的真实用例具有大量嵌套循环,请考虑不这样做,而是;这是一种严重的设计气味。

      void nested_loop(const int levels, const int comparator, const int level = 0, const int accumulator = 0)
      {
         if (level < levels) {
            for (int i = 0; i < 6; i++) {
               nested_loop(levels, comparator, level + 1, accumulator + i);
            }
         }
         else {
            if (accumulator == comparator) {   // your if (z+y+x==f)
               //do something
            }
         }
      }
      
      int main() {
         const int levels = 3;
         const int f = 42;
      
         nested_loop(levels, f);
      }
      

      Live demo.

      【讨论】:

        猜你喜欢
        • 2018-12-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-21
        • 1970-01-01
        • 1970-01-01
        • 2011-12-05
        相关资源
        最近更新 更多