我有一个下面的函数,它是递归的,因为它在结束时调用自己,但是如何将它更改为非递归?
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);
}
}
}
答案 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在汇编程序代码中添加了不同的注释。哦,文件名仍然不同。