假设有类似下面的多重循环:
for(i=0; i<3; i++)
for (j=2; j<6; j++)
for (k=5; k<16; k++)
for (l=3; l<5; l++)
{
//do something with i,j,k,l
}
像上面一共有4重循环,有时候可能更多,如何将任意多重循环用2重循环来改写呢?
方法1:
const intupper[4]= {3,6,16,5};
const int lower[4]= {0,2,5,3};
int index[4]= {0,2,5,3};
int level;
do{
level=3;
//do something with index[], such as print
while(level>=0 && (++index[level]>=upper[level])){
index[level]=lower[level];
level--;
}
}while (level>=0);
1) ++index[level]
2) 判断当前的level是不是已经到边界(upper[level]),
如果已到边界,将index[level]重新置为起始值,并将level减1,也就是到了上面一层;
否则跳过内层循环。
如果还想不明白,在//do something的地方打印出index[0],index[1], index[2], index[3]即可,它们分别对应前面的i,j,k,l。也可以用下面的方法,原理差不多:
方法2:
do {
//do something with index[], such as print
for (level=3; level>=0; level--) {
index[level]++;
if (index[level] >= upper[level])
index[level] = lower[level];
else
break;
}
} while(level >= 0);
方法3:
说起循环我们就应该想到递归,所以我们也可以用递归来改写这个多重循环,原理跟上面的方法差不多,只是外层循环用递归代替了。代码如下:
void dfs(int arr[], int id) {
int i;
//do something with arr[], such as print
if ((arr[0]==upper[0]-1) && (arr[1]==upper[1]-1) && (arr[2]==upper[2]-1) && (arr[3]==upper[3]-1))
return;
for (i=3; i>=0; i--) {
arr[i]++;
if (arr[i]>=upper[i])
arr[i]=lower[i];
else
break;
}
dfs(arr, i);
}
调用的时候用dfs(index, 3)即可。