我正在编写一个程序,在递归x
元素之前计算所有元素的摘要。它总是返回0.请帮助我 - 你能解释一下当我在main中调用SumBeforeX
函数时它是如何有效地工作的吗?
这是我的代码和
#include <stdio.h>
int SumBeforeX(int a[], int n, int x)
{
int i = 0;
static int s = 0;
if (n == 0)
return 0;
if (a[i] == x)
s+=SumBeforeX(a, i -1, x) +a[i-1];
return s;
}
void main()
{
int a[] = {2,6,13,17,47,8};
printf("%d",SumBeforeX(a,6,13));
_getch();
}
答案 0 :(得分:2)
user3629249 给出的答案已经解释了为什么SumBeforeX()
总是返回0
而 Felix Palmen 回答谈到了递归和非递归方式解决问题。这个答案只是为了让您了解使用尾递归计算"x"
元素之前的总和:
int SumBeforeX(const int *a, int n, int x, int sum)
{
if (n == 0) return 0;
if (x == *a) return sum;
return SumBeforeX(a + 1, n - 1, x, sum + *a);
}
在这里,您可以看到我已向函数sum
添加了一个参数SumBeforeX
,并将元素总和累积到其中。你可以这样称呼它:
printf("%d\n", SumBeforeX(a, 6, 13, 0));
似乎你正在学习递归,它也很适合熟悉尾递归。
如果函数返回后除了返回其值之外没有任何操作,则称函数调用是尾递归的。尾递归函数可以很容易地转换为迭代函数,因此编译器也可以通过消除递归来优化这些函数的代码,也就是说,尾递归调用在常量堆栈空间中运行,即它们不需要创建新的堆栈当他们递归地调用自己时的帧。检查以下内容以获得更好的想法:
1)Tail Recursion
2)How exactly does tail recursion work?
答案 1 :(得分:0)
我想预期的解决方案看起来有点像这样:
int sumBeforeX(const int *a, int x)
{
if (x == *a) return 0; // termination condition
return *a + sumBeforeX(a+1, x); // recursive step
}
要理解这一点,请注意,数组不能在C中传递,因此它们在函数参数中的类型会调整为相应的指针类型,而是传递指向第一个元素的指针。我在上面的代码片段中明确说明了这一点,直接写了指针类型。
const
只是一点改进:函数永远不会通过这个指针修改你的数组,所以也要明确这个。
另请注意此实施从不指定的任何内容。这是函数式编程的典型属性,递归特别适用于函数式编程。函数调用没有副作用。
旁注:不要在现实世界的C代码中递归写入,如果幸运的话,编译器会优化递归(在这个简单的情况下,一个好的编译器应该这样做),但是不应该这样做如果递归保持不变,性能通常会受到影响,如果递归真的很深,你可能会遇到堆栈溢出的风险。因此,为了完整性,现实世界的代码看起来应该更像:
int sumBeforeX(const int *a, int x)
{
int sum = 0; // accumulator to replace recursion
while (*a != x) sum += *a++;
return sum;
}
答案 2 :(得分:0)
关于:当我在main中调用SumBeforeX函数时,你能解释它是如何有效运作的吗?
#include <stdio.h>
int SumBeforeX(int a[], int n, int x)
{
int i = 0;
static int s = 0;
if (n == 0)
return 0;
if (a[i] == x)
s+=SumBeforeX(a, i -1, x) +a[i-1];
return s;
}
void main()
{
int a[] = {2,6,13,17,47,8};
printf("%d",SumBeforeX(a,6,13));
_getch();
}
首次执行SumBeforex()
n
的值为6,因此没有提前退出i
的值为0,因此a[i]
的值为2 x
的值为13