1

我正在为我的 Computing I 类编写一个小程序,其中程序接受用户决定的多个整数并计算点积。我能够使用迭代方法成功地做到这一点,但现在我们还必须使用递归来做到这一点。我计算点积的函数返回了广泛的错误数字。有时它只会返回数组中最后两个值的乘积的两倍,此时还有 4 个其他集合没有被添加进去。其他时候,我将有 2 个包含 3 个小数字的数组,并且返回的值是 80 千。这是递归函数:

//A and B are the arrays that will be dotted together, and n is number of
//elements in each array
int dotP( int *A, int *B, int n ) {
   if( n==1 ) return A[0] * B[0] ;
   return A[n-1] * B[n-1] + dotP( &A[n-1], &B[n-1], n-1);
}
4

3 回答 3

3

究竟发生了什么

A[n-1]*B[n-1] + A[n-1 + n-2]*B[n-1 + n-2]+....

发生这种情况是因为对于第二次递归调用,您正在传递n-1元素的地址。当它A[n-2]在第二次调用中计算时,它有效地指向从第一个n-2元素开始的第 ndn-1个元素,即2*n-3从数组的第一个元素开始的 rd。

之后数组中的值n是垃圾(假设您分配n了元素,或者您可能分配了更多n但没有初始化它们)。因此,您得到随机答案。您无需将当前数组元素的地址传递给每个递归调用。您只需传递第一个元素的地址,即Aor 或&A[0]。然后你的代码工作正常。这是怎么做的:

int dotP( int *A, int *B, int n ) {
if( n==1 ) return A[0] * B[0] ;
return A[n-1] * B[n-1] + dotP( A, B, n-1) ;
}

由于AB已经是指针,您只需直接传递它们。希望这会有所帮助。

于 2013-09-24T02:50:25.387 回答
2

不是

... + dotP( &A[n-1], &B[n-1], n-1 );

... + dotP( &A[0], &B[0], n-1 );

因为看起来您想要处理数组的最后一项,所以将前 (n-1) 个元素传递给递归调用。请记住,数组总是作为指向其第一个元素的指针来处理,除非您正在做比这更棘手的事情。

问题已解决,但出于教育目的,请尝试此替代方法:您可以处理第一个元素并传递其余元素,即“尾巴”,这可能更让 LISP 粉丝满意:

return A[0] * B[0] + dotP( &A[1], &B[1], n-1 );

或者,您可以传递 A+1 而不是 &A[1]。

于 2013-09-24T02:45:04.337 回答
0

为什么不更好地使用:

int dotP( int *A, int *B, int n ) 
{
   if (n) return A[0] * B[0] + dotP(A + 1, B + 1, n-1);
   else return 0;
}

或更紧凑的形式:

int dotP(int *A, int *B, int n)
{
    if (n) return A[0] * B[0] + dotP(++A, ++B, --n);
    else return 0;
}
于 2014-09-24T12:48:27.390 回答