将递归函数更改为非递归函数

时间:2012-12-14 16:52:51

标签: c recursion

我有一个下面的函数,它是递归的,因为它在结束时调用自己,但是如何将它更改为非递归?

int ACR(int q, int*a, int n, int i){
    if(i>=n){
        return 0;
    }
    else{
        if(a[i] == q){
            return 1;
        }
        else{
            return ACR(q,a,n,i+1);
        }
    }
}

4 个答案:

答案 0 :(得分:4)

您可以使用循环

int ACR(int q, int*a, int n, int i){
    int j;
    for (j=i; j<n; j++) {
        if (a[j] == q) {
            return 1;
        }
    }
    return 0;
}

每次调用ACR的迭代版本都会测试数组a的单个元素是否与q的值匹配。如果我们在没有匹配的情况下到达数组的末尾,我们返回0.很容易将其转换为循环。

请注意,如果您始终要搜索完整数组(即从索引0开始),则i可能不再需要作为参数。

答案 1 :(得分:2)

看起来它在索引i和n之间搜索q,不包括。

这将是:

int ACR(int q, int*a, int n, int i) {
    int count;
    for(count =i ; count<n; count++)
         if(a[count] == q)
            return 1;
    return 0;
}

答案 2 :(得分:1)

试试这个,这是我能想到的最短路:

int ACR(int q, int*a, int n, int i) {
    while (i < n && a[i] != q) i++;
    return i < n ? 1 : 0;
}

答案 3 :(得分:0)

你为什么要改变它? (我想这是一个练习......)

这是有趣的事情:

递归版(你的,括号较少):

$ cat acr.c
int has(int q, int*a, int n, int i) {
  if (i >= n)
    return 0;
  else if (a[i] == q)
    return 1;
  else
    return has(q,a,n,i+1);
}

迭代版本(我的,但与其他人相似):

$ cat aci.c
int has(int q, int* a, int n, int i) {
  for (; i < n; ++i)
    if (a[i] == q) return 1;
  return 0;
}

编译汇编代码并进行比较:

$ diff <(gcc-4.7 -std=c99 -S -o - -O3 acr.c) <(gcc-4.7 -std=c99 -S -o - -O3 aci.c)
1c1
<       .file   "acr.c"
---
>       .file   "aci.c"
9,10c9,10
<       cmpl    %ecx, %edx
<       jle     .L5
---
>       cmpl    %edx, %ecx
>       jge     .L5

所以重写改变了一个简单的细节:一个检查n ≤ i,另一个检查i ≥ n。 (哦,源文件的名称不同。)

这是同一个测试,有clang:

$ diff <(clang -std=c99 -S -o - -O3 acr.c) <(clang -std=c99 -S -o - -O3 aci.c)
1c1
<       .file   "acr.c"
---
>       .file   "aci.c"
12c12
< .LBB0_1:                                # %tailrecurse
---
> .LBB0_1:                                # %for.cond
17c17
< # BB#2:                                 # %if.else
---
> # BB#2:                                 # %for.body

Clang在汇编程序代码中添加了不同的注释。哦,文件名仍然不同。