关于递归函数的问题?

时间:2011-03-24 14:24:31

标签: c recursion

我有一本C书的递归函数如下:

void print(int a[], int n)
{   if (n<=0)  return ;
     printf("%d\n", a[0]);
     print(&a[1], n-1);
}

我已经运行并且此函数打印指定数组的所有元素。但我真的不明白这个功能是如何工作的,所以我可以打印数组的所有元素。 请问有人能给我一个明确的解释吗?

11 个答案:

答案 0 :(得分:5)

&a[1]是数组的第二个元素的地址,它实际上是第一个元素之后的数组部分的地址。因此,在打印参数数组的第一个元素后,

print(&a[1], n-1);

将数组的剩余部分传递给自己,同时将长度减少一个。

例如,如果您使用数组print{1, 2, 3, 4, 5}致电n == 5,则事件和调用链如下:

  1. 打印第一个元素(1)
  2. 使用数组的剩余部分调用自身,即{2, 3, 4, 5}n == 4
    1. 打印第一个元素(2)
    2. 使用数组的剩余部分调用自身,即{3, 4, 5}n == 3
      1. 打印第一个元素(3)
      2. 使用数组的剩余部分调用自身,即{4, 5}n == 2
        1. 打印第一个元素(4)
        2. 使用数组的剩余部分调用自身,即{5}n == 1
          1. 打印第一个元素(5)
          2. 使用数组的剩余部分调用自身,即{}n == 0
            1. n<=0 - &gt;返回
          3. 返回
        3. 返回
      3. 返回
    3. 返回
  3. 返回

答案 1 :(得分:2)

此函数将数组的剩余部分作为参数以及它包含的元素数量。每次打印第一个元素,然后递归调用剩余部分。这是一个例子:

array: 1, 2, 3, 4, 5, 6; N = 6
array: 2, 3, 4, 5, 6; N = 5
array: 3, 4, 5, 6; N = 4
array: 4, 5, 6; N = 3
array: 5, 6; N = 2
array: 6; N = 1
array: ; N = 0 return;

答案 2 :(得分:1)

数组基本上是指向第一个元素开头的指针,所以你的代码基本上是这样的:

void print(int *a, int n)
{   if (n<=0)  return ;
     printf("%d\n", *a);
     print(a+1, n-1);
}

递归调用是传入指向数组中下一项的指针并减少计数,这是您在递归终止条件中使用的。

答案 3 :(得分:1)

所以它做了以下事情:

  1. 检查数组中是否有任何元素,如果没有,只需返回。
  2. 打印数组中的第一个元素,因为我们知道我们至少有一个。
  3. 再次调用自身指向数组中的第二个元素,并从大小中减去1,从而再次从#1开始。

答案 4 :(得分:1)

了解递归的好方法IMHO是在调试器中运行代码,并观察调用堆栈和变量。

答案 5 :(得分:1)

  • 如何打印零大小的数组? 容易:你没有
    这是你的if (n<=0) return;

  • 如何使用1个元素打印数组? 简单:只需打印元素 并将其从数组中删除并按原样打印生成的零大小数组
    这是你的printf("%d\n", a[0]);

  • 如何使用2个元素打印数组? 简单:打印第一个元素将其从阵列中移除并按原样打印生成的一个大小的数组
    这是你的print(&a[1], n-1);


  • 如何使用N个元素打印数组?
    简单:打印第一个元素,将其从数组中删除,然后打印生成的较小数组

答案 6 :(得分:0)

如果n为零(或更小),则不执行任何操作,因此递归停止。如果n&gt; 0,然后打印a[0]并以n-1n递归调用自身(因此递归进行时为0),&a[1]a,即它在每次递归调用中递增指针a。请记住,C中的数组参数是指针参数的语法糖。

因此,您发布的代码相当于:

void print(int *a, int n)
{
    if (n > 0) {
        printf("%d\n", *a);
        print(a+1, n-1);
    }
}

答案 7 :(得分:0)

如果您可以验证以下算法是否适用于打印数组,您应该能够理解C代码的工作原理,因为它是直接翻译。

打印数组的n个元素:

  • 如果要求您不打印任何元素,请停止。
  • 否则:
    • 打印第一个元素,然后
    • 打印阵列其余部分的n-1个元素(使用相同的配方)。

答案 8 :(得分:0)

每次打印调用都会这样做:

  1. 打印数组a的第n个元素并减少剩余元素(n)的数量以进行打印。(看看它是否意味着:要打印多少元素)。
  2. 调用它自行递减(n - 1:少一个要打印的元素)将指针传递给数组的第二个元素(&amp; a [1]),因为第一个元素(a [0])已经被打印
  3. 你究竟不懂什么?

答案 9 :(得分:0)

它相当于一个循环:

int i ;
for (i = 0 ; i< n ; i++) { 
printf("%d\n",a[i]);
}

为什么呢?好吧,递归总是查看第一个元素并打印它,然后通过查看第二个元素中的数组(现在是下一个迭代中的'first'),它们前进到下一个元素。 你的停止条件是当没有剩余元素时 - 即一个长度为0的数组。

答案 10 :(得分:0)

该函数接受一个数组和数组的长度。

if(n<=0) return;

如果数组的长度为&lt; = 0,则函数返回。

printf("%d\n", a[0]);

数组的第一个元素,即元素0。

print(&a[1], n-1);

&amp; a [1]获取指向数组第一个元素的指针。数组和指针可以互换使用,因此当函数传递给函数时,函数可以将它视为一个新数组,从前一个数组的第二个元素开始,长度减少一个。