将嵌套循环转换为递归

时间:2017-06-06 18:36:59

标签: c recursion

我使用了3个嵌套循环。现在我想将这些循环转换为递归。 还有一种将循环转换为递归的通用方法吗?

#include <stdio.h>

#define f(x, y, z) ((x + y) * (y + z))

int main()
{
    int test_case, p, q, r, i, j, k, a[100001], b[100001], c[100001], sum;
    scanf("%d", &test_case);
    while (test_case--) {
        scanf("%d%d%d", &p, &q, &r);
        sum = 0;
        for (i = 0; i < p; i++) {
            scanf("%d", &a[i]);
        }
        for (i = 0; i < q; i++) {
            scanf("%d", &b[i]);
        }
        for (i = 0; i < p; i++) {
            scanf("%d", &c[i]);
        }
        for (i = 0; i < q; i++) { // I have convert this to recursion.
            for (j = 0; j < p; j++) {
                for (k = 0; k < r; k++) {
                    if (b[i] >= a[j] && b[i] >= c[k]) {
                        sum += f(a[j], b[i], c[k]);
                    }
                }
            }
        }
        printf("%d\n", sum % 1000000007);
    }
    return 0;
}

3 个答案:

答案 0 :(得分:2)

像这样的循环:

for (int i=0; i<n; i++) {
    func(i);
}

可以转换为递归:

void rec_fun(int i,int n) {
    if (!(i<n)) return;
    func(i);
    rec_fun(i+1,n);
}
...
rec_fun(0,n);

所以:

for (i = 0; i < q; i++) { // I have convert this to recursion.
    for (j = 0; j < p; j++) {
        for (k = 0; k < r; k++) {
            if (b[i] >= a[j] && b[i] >= c[k]) {
                sum += f(a[j], b[i], c[k]);
            }
        }
    }
}

可翻译为:

void rec_k(int k,int r,int i,int j) { // k-loop
    if (!(k<r)) return;
    if (b[i] >= a[j] && b[i] >= c[k]) {
        sum += f(a[j], b[i], c[k]);
    }
    rec_k(k+1,r,i,j); // recurse
}

void rec_j(int j,int p,int i,int r) { // j-loop
    if (!(j<p)) return;
    rec_k(0,r,i,j); // inner loop
    rec_j(j+1,p,i,r); // recurse
}

void rec_i(int i,int q,int p,int r) { // i-loop
    if (!(i<q)) return;
    rec_j(0,p,i,r); // inner loop
    rec_i(i+1,q,p,r); // recurse
}
...
rec_i(0,q,p,r);

我不确定这是否更具可读性或有用性,但它符合您的初始需求。

答案 1 :(得分:1)

让我们假设此代码的意图是仅计算总和。

您可以将功能设为

int recurse_sum(int i, int j, int k) {
      int res = .... // Logic for calculating sum for these indices i, j, k.
      k++;
      if (k==r) {
          k = 0;
          j++;
      }
      if(j==p){
          j=0;
          i++;
      }
      if(i==q){
          return res;
      }
      return res + recurse_sum(i,j,k);
}

现在您只需拨打recurse_sum(0,0,0); 其余参数可以是全局的,也可以只与i,j,k一起传递。

我希望这会有所帮助。

编辑:

正如@dlasalle所提到的,通过将调用放在函数的末尾,可以使这个代码对尾调用递归优化开放。

在这种情况下,您可以使用以下版本。

int recurse_sum(int i, int j, int k, int sum) {
      int res = .... // Logic for calculating sum for these indices i, j, k.
      k++;
      if (k==r) {
          k = 0;
          j++;
      }
      if(j==p){
          j=0;
          i++;
      }
      if(i==q){
          return res + sum;
      }
      return recurse_sum(i,j,k,res+sum);
}

此处函数以从内部调用返回值结束,因此可以轻松优化。

在这种情况下,它必须被称为recurse_sum(0,0,0,0);

答案 2 :(得分:0)

感谢@ Jean-BaptisteYunès。

我对代码进行了这些更改,将其转换为递归。

#include<stdio.h>
#define f(x, y, z) ((x + y)*(y + z))
int sum=0;
void rec_k(int k,int r,int i,int j,int a[],int b[],int c[]) { // k-loop
    if (!(k<r)) return;
    if (b[i] >= a[j] && b[i] >= c[k]) {
        sum += f(a[j], b[i], c[k]);
    }
    rec_k(k+1,r,i,j,a,b,c);
}

void rec_j(int j,int p,int i,int r,int a[],int b[],int c[]) { // j-loop
    if (!(j<p)) return;
    rec_k(0,r,i,j,a,b,c);
    rec_j(j+1,p,i,r,a,b,c);
}

void rec_i(int i,int q,int p,int r,int a[],int b[],int c[]) { // i-loop
    if (!(i<q)) return;
    rec_j(0,p,i,r,a,b,c);
    rec_i(i+1,q,p,r,a,b,c);
}
int main() {
    int test_case, p, q, r, i, j, k, a[100001], b[100001], c[100001];
    scanf("%d", &test_case);
    while(test_case--) {
        scanf("%d%d%d", &p, &q, &r);
        sum=0;
        for(i=0;i<p;i++) {
            scanf("%d", &a[i]);
        }
        for(i=0;i<q;i++) {
            scanf("%d", &b[i]);
        }
        for(i=0;i<p;i++) {
            scanf("%d", &c[i]);
        }
        rec_i(0,q,p,r,a,b,c);
        printf("%d\n", sum%1000000007);
    }
    return 0;
}