为循环嵌套的变量
variable nested for loops
我正试图弄清楚如何使用递归来执行n级嵌套循环。例如,如果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
为了提高效率,我避免了递归。此外,它不使用任何特定的c++东西——它在c上也能很好地工作。
我们正试图创建N个嵌套的";对于";循环。而不是使用
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!
}
}
就这样。希望这些评论能清楚地表明它的意图。我认为它应该非常高效——几乎和真正的嵌套for循环一样多。大多数开销在一开始都是一次性的,所以这应该比使用递归函数等更有效
具有多个循环的递归算法的基本结构如下:
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);
这里有一个普通的旧C++的例子。首先,我为每个维度做一个范围的向量,称为maxes
。如果所有指数的总和是2,那么我打印做了一些事情。在示例I中,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
只计算每个递归函数的深度,并计数到f
。。
void myRecursiveFunc(int depth){
if(depth == f)
//do something
return;
else{
myRecursiveFunc(depth + 1);
}
}
如果你真的想,你可以对x、y和z使用三个不同的函数。
您对为什么要这样做含糊其辞。对于启动器,一个可能的解决方案是用递归函数替换每个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);
最后,你可以将所有这些合并为一个函数。然而,仅仅因为递归是可能的就使用递归从来都不是一个好主意。
你可以这样写,但是。。。我不会的。这是一个令人困惑的代码,不会给您带来任何好处。如果你想要它是因为你的真实用例有大量的嵌套循环,那么考虑一下不要这样做;这是一种严重的设计气味。
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);
}
现场演示
在"C"
概念
- 创建一个二维数组(arr[level][2]),其中第一个元素开始,第二个元素结束。
x[3][2] = {{0, 10}, {5, 20}, {2, 60}};
- 正在创建另一个具有起始元素的数组。
y[3] = {0, 5, 2};
- 我们创建了第二个数组,因为在循环期间,我们将更改"的第一个元素;x〃;数组
代码
#include <stdio.h>
int main(){
// bruteforce
int level = 10;
int start[10] = {0, 0, 0, 0};
int x[10][2] = {{0, 5}, {0, 5}, {0, 5}, {0, 5}};
for (int i = 1;i < level; ++i){
x[i][1] = x[i][1] + 1;
}
while(3>2){
// Your code here
//
printf("%d %d %d %dn", x[0][0], x[1][0], x[2][0], x[3][0]);
// variable loop code
// ==== Not To Modify ====
int a = 0;
int b = 0;
for(int i = 0;i < level; ++i){
if (x[i][0] >= x[i][1])
{
if(i != level-1){
x[i][0] = start[i];
x[i+1][0] = x[i+1][0] + 1;
}else{
a = 1;
}
b = 1;
}else{
if(b == 0){
x[0][0] = x[0][0] + 1;
b = 1;
}
}
}
if(a == 1){
break;
}
}
return 0;
}
这是一个迟来的答案,但也许它会对某人有所帮助。
以下是我在没有递归函数的c++中的解决方案
int n_loops{3}; //number of nested for loops
int loops_idx[n_loops]; //like i,j,k but in an array
for (int i = 0; i < n_loops; i++)
loops_idx[i]=0;
int max_idx[n_loops]{3,2,4}; // like in for(; i < counter ;), but the counters in an array
bool is_finished = false;
int debug_n_of_execution{0};
while (!is_finished)
{
for (; loops_idx[0]<max_idx[0]; loops_idx[0]++)
{
/*
some code with loops_idx array as i,j,k...
*/
++debug_n_of_execution;
for (int i = 0; i < n_loops; i++)
std::cout<<loops_idx[i]<<" ";
std::cout << "n";
}
--loops_idx[0]; //to cancel last increment
//Here it will increment the last loop_idx which isn't equal to max_idx[i]-1
//eg. after first above for loop loops_idx will be (max-1, 0, 0)
//So it will be after this loop (0, 1, 0) and start from the beginning...
for (int i = 0; i < n_loops+1; i++) //+1 to know if all loops are finished
{
if (i == n_loops)
{is_finished= true; break;}
if(loops_idx[i]==max_idx[i]-1)
continue;
++loops_idx[i];
for (int j = 0; j < i; j++) //make any previous loop = 0
loops_idx[j]=0;
break;
}
}
//just to check
int debug_perfect_n_of_execution{max_idx[0]};
for (int i = 1; i < n_loops; i++)
debug_perfect_n_of_execution*= max_idx[i];
std::cout<<"Number of execution: "<<debug_n_of_execution<<" = "<<debug_perfect_n_of_execution;
assert(debug_n_of_execution==debug_perfect_n_of_execution);
std::cout << "nTests Finished";
结果是:
0 0 0
1 0 0
2 0 0
0 1 0
1 1 0
2 1 0
0 0 1
1 0 1
2 0 1
0 1 1
1 1 1
2 1 1
0 0 2
1 0 2
2 0 2
0 1 2
1 1 2
2 1 2
0 0 3
1 0 3
2 0 3
0 1 3
1 1 3
2 1 3
Number of execution: 24 = 24
Tests Finished
- 如何初始化对类内变量的静态引用,以便在嵌套类中使用
- 如何访问嵌套在命名命名空间中的未命名命名空间变量?
- GCC5:嵌套变量模板不是函数模板?
- 释放指向保留嵌套变量内存地址的结构的指针
- 嵌套的类成员变量不可访问.链表设置.V、下一个和新的问题
- 声明嵌套在模板参数中的类型的变量?
- 具有可变变量的嵌套C++模板
- 在嵌套循环中C++变量重新声明
- 访问嵌套块中重新定义的变量
- 解决具有嵌套模板化变量的 Visual Studio 内部编译器错误
- 许多变量,没有嵌套循环的最佳方法
- 模板类中嵌套类的C 静态成员变量
- C++嵌套循环,外部有变量
- C++ 是否可以使用对变量的引用来简化这种嵌套循环模式?
- LLVM - 如何使嵌套函数看到外部函数的变量
- 嵌套类:如何访问封闭类中的成员变量
- 如何更新嵌套lambda功能(C )中的变量
- 访问嵌套类中的变量时出现问题
- 使用泛型函数调用打印结构的所有嵌套成员变量
- 缩减嵌套模板的类型变量非类型列表