以下程序的输出是24.但我无法理解函数f1(参数)的行为。
在m1和m2中有一个f1的递归调用。考虑到m1和m2保持函数f1的堆栈。 m1堆栈将包含:
1]0,12,a 2]0,6,a 3]0,3,a 4]0,1,a 5]0,0,a
m2堆栈将包含:
1]13,12,a 2]20,6,a 3]24,3,a 4]26,1,a 5]27,0,a
m1和m2的值是多少?请解释递归函数的这种行为。
#include <stdio.h>
main()
{
int i, n, m, b, x[25];
int f1(int, int, int j[25]);
for(i=0;i<25;i++) x[i] = i;
i=0; m = 24;
b=f1(i, m, x);
printf("res %d\n",b);
}
int f1( int p, int q, int a[25])
{
int m1,m2;
if (q==0)
return(a[p]);
else
{
m1 = f1 (p, q/2, a);
m2 = f1(p+q/2+1,q/2,a);
if(m1<m2)
return (m2);
else
return(m1);
}
}
答案 0 :(得分:2)
在这里你不能想到m1堆栈和m2堆栈,因为对f1的非终止调用导致m1和m2递归调用。
要分析正在发生的事情,请尝试使用较小的p和q值。
f1( 0, 1, a)
m1 = f1( 0, 0, a); /* q/2 == 1/2 == 0 */
/* q now 0 so return a[0] */
m2 = f1( 1, 0, a);
/* q now 0 so return a[1] */
overall result the larger of a[0] and a[1].
现在尝试f1(0,2,a)等等,直到你看到发生了什么。
答案 1 :(得分:2)
嗯,理解代码有两点:
在尝试理解此类代码时,始终帮助我的是:
清理C代码。在这种情况下,它意味着:
精神上跟踪初始化并重写为静态初始化,以便您看到值的样子:
int x [25] = {0,1,2,3,4,5,6,7,8,9,10,11,12, 13,14,15,16,17,18,19,20,21,22,23,24};
摆脱对i
和x
的无用作业,这样您就可以进行初步调用。
将函数重写为数学符号,伪代码甚至是人类语言。
f(p, q, array) = larger of f(p, q/2, array) and f(p+q/2+1, q/2, array)
如果你继续使用人类语言,你会清楚地看到应该做什么。
现在我故意说“应该这样做”。 (p, q/2)
和(p+q/2+1, q/2)
看起来像第一个和第二个半......除非它们不是。
代码应该返回24,但这是完全错误的,问题中引用的堆栈实际证明了这一点。 m2堆栈包含最后一个点“f1(27,0,a)”,并且该调用将执行[27],但该数组只有25个元素! (通过纯粹的机会,上面的内存可能是0初始化的,所以它确实返回了24,但如果它是由一些调试模式初始化的(我见过0xdeadbeef,0xa5a5a5a5和0xcccccccc),它会返回那个)。
在C中它是设计的(并且C ++在任何地方都使用它们)最容易使用半开间隔。 [开始,一个接一个结束]或开始+长度,很好地相互转换。但是这里函数得到(start,length-1)并且在内部处理它不一致。
作为一名学生,你必须能够理解这样的代码,因为你会遇到很多糟糕的,不可读的错误代码,只能在野外偶然发挥作用。但是如果你曾经提出这样的话,那么你将无法通过考试。