递归函数的返回值

时间:2011-08-15 07:21:12

标签: c

以下程序的输出是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);
 }
}

2 个答案:

答案 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)

嗯,理解代码有两点:

  1. 在可怕的C和
  2. 堆中揭示实际算法
  3. 了解递归函数本身。
  4. 在尝试理解此类代码时,始终帮助我的是:

    1. 清理C代码。在这种情况下,它意味着:

      1. 精神上跟踪初始化并重写为静态初始化,以便您看到值的样子:

        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};

      2. 摆脱对ix的无用作业,这样您就可以进行初步调用。

    2. 将函数重写为数学符号,伪代码甚至是人类语言。

      f(p, q, array) = larger of f(p, q/2, array) and f(p+q/2+1, q/2, array)
      

      如果你继续使用人类语言,你会清楚地看到应该做什么

    3. 现在我故意说“应该这样做”。 (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)并且在内部处理它不一致。

      作为一名学生,你必须能够理解这样的代码,因为你会遇到很多糟糕的,不可读的错误代码,只能在野外偶然发挥作用。但是如果你曾经提出这样的话,那么你将无法通过考试。