我被要求编写一个递归代码来打印数组。一位朋友给我看了这段代码:
include <stdio.h>
int i=0;
void print(int A[], int n)
{
if(i<n)
{
printf("%d ", A[i]);
i++;
print(A, n);
}
}
int main()
{
int A[3]={3, 5, 2};
print(A, 3);
return 0;
}
从技术上讲,它是递归的,因为函数调用自身,但我认为简单 !!它不会将问题分解为更小的问题或类似的问题。所以,感觉像作弊。伪装好像是递归。
此代码中的函数可以考虑递归吗?这是使用递归的好方法吗?
这种形式怎么样:
#include <stdio.h>
void print(int A[], int n, int i)
{
if(i<n)
{
printf("%d ", A[i]);
print(A, n, i+1);
}
}
int main()
{
int A[3]={3, 5, 2}, i=0;
print(A, 3, i);
return 0;
}
答案 0 :(得分:4)
此代码中的函数可以考虑递归吗?
是的,当函数可以直接调用或时,会发生递归。
这是使用递归的好方法吗?
没有。虽然某些编译器可能会优化代码,但代码可能会导致n
递归级别并导致stack overflow
更好的选择是减半问题。这在每一步都打破了2中的问题。
void print(int A[], int n, int i) {
if (i<n) {
A += i; n -= i; // zero offset A and n
int mid = n/2;
print(A, mid, 0); // print left side of A
printf("%d ", A[mid]); // print middle of A
int right = n - mid - 1;
print(A + mid + 1, right, 0); // print right side of A
}
}
如果n
为1000,则上面的迭代深度可能为log2(1000)或大约为10而不是1000.无界n
是一个可以滥用递归的原因。确保递归深度不过分。
请注意,实际上并不需要参数i
。
void printA(int A[], size_t n) {
if (n > 0) {
size_t mid = n/2;
printA(A, mid); // print left side of A
printf("%d ", A[mid]); // print middle of A
size_t right = n - mid - 1;
printA(A + mid + 1, right); // print right side of A
}
}
答案 1 :(得分:2)
是的,这是一个递归函数,因为它自称。
此外,该函数确实将问题解决为较小的问题 - 在这种情况下,恰恰是一个较小的问题:从索引i+1
开始而不是从索引i
打印数组。由于边界大于i
,因此问题较小。
换句话说,递归是有根据的:n-i
的值在每次调用时都在减少,n-i==0
的边缘情况是平凡处理的,而不是递归的
答案 2 :(得分:1)
无论函数中的行数是多少,如果它自己调用它都是递归的。
void print(int A[], int n) {
if(n == 0)
printf("%d", *A);
print(++A, --n);
}
答案 3 :(得分:1)
您可以传递数组的static
元素地址和starting
元素地址,而不是使用last
变量,而是执行相同的任务。
void print(int *A_start, int *A_end) {
if(A_start < A_end) { /* call the function itself until A_start not reaches A_end */
printf("%d ", *A_start);
A_start++;
print(A_start,A_end);
}
}
int main() {
int A[3]={3, 5, 2};
int ele = sizeof(A)/sizeof(A[0]);
print(A,A+ele);
return 0;
}