Вопрос о рекурсивной функции? - PullRequest
3 голосов
/ 24 марта 2011

У меня есть рекурсивная функция из книги C следующим образом:

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

Я запустил, и эта функция печатает все элементы указанного массива. Но я действительно не понимаю, как работает эта функция, чтобы я мог печатать все элементы массива. Кто-нибудь может дать мне четкое объяснение, пожалуйста?

Ответы [ 11 ]

5 голосов
/ 24 марта 2011

&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 -> возврат
          3. Возвращение
        3. Возвращение
      3. возвращение
    3. Возвращение
  3. Возвращение
2 голосов
/ 24 марта 2011

Эта функция принимает в качестве аргументов оставшуюся часть массива и количество элементов в нем.Каждый раз, когда вы печатаете первый элемент, а затем рекурсивно вызываете оставшуюся часть.Вот пример:

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;
1 голос
/ 24 марта 2011
  • Как вы печатаете массив нулевого размера? Легко: вы не
    Это ваш if (n<=0) return;

  • Как вы печатаете массив с 1 элементом? Легко: просто распечатайте элемент , удалите его из массива и напечатайте получившийся массив нулевого размера, как раньше
    Это ваш printf("%d\n", a[0]);

  • Как вы печатаете массив с 2 элементами? Легко: напечатайте первый элемент и , удалите его из массива и напечатайте получившийся одномерный массив, как и раньше
    Это ваш print(&a[1], n-1);


  • Как распечатать массив с N элементами?
    Легко: напечатать первый элемент, удалить его из массива и напечатать полученный меньший массив
1 голос
/ 24 марта 2011

Хороший способ понять рекурсию IMHO - запустить код в отладчике и посмотреть стек вызовов и переменные.

1 голос
/ 24 марта 2011

Так что делает следующее:

  1. Проверьте, есть ли какие-либо элементы в массиве, если нет, просто верните.
  2. Напечатайте первый элемент в массиве, так как мы знаем, что у нас есть хотя бы один.
  3. Вызывает себя снова, указывая на 2-й элемент в массиве и вычитая 1 из размера, таким образом снова начиная с # 1.
1 голос
/ 24 марта 2011

Массивы - это, в основном, указатели на начало первого элемента, так что вы код, по сути, такой:

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

Рекурсивный вызов передает указатель на следующий элемент в массиве и уменьшает количество, который используется в вашем рекурсивном состоянии завершения.

0 голосов
/ 24 марта 2011

Функция принимает массив и длину массива.

if(n<=0) return;

Если длина массива <= 0, функция возвращает. </p>

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

печатается первый элемент массива, элемент 0.

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

& a [1] получает указатель на первый элемент массива. Массивы и указатели можно использовать взаимозаменяемо, поэтому, когда они передаются функции, функция может обрабатывать ее как новый массив, начиная со второго элемента предыдущего массива и с длиной на единицу меньше.

0 голосов
/ 24 марта 2011

эквивалентно циклу:

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

почему? ну, рекурсия всегда смотрит на первый элемент и печатает его, и они переходят к следующему элементу, просматривая массив из 2-го элемента (который теперь будет «первым» в следующей итерации).
ваше условие остановки - когда больше не осталось элементов - то есть массив длиной 0.

0 голосов
/ 24 марта 2011

Каждый вызов для печати сделать это:

  1. вывести n-й элемент массива a и уменьшить число оставшихся элементов (n) для печати (посмотрите на n так, как оно означает: сколько элементов осталось напечатать).
  2. Назовите его самоуменьшающимся (n - 1: один элемент меньше для печати), передав указатель на второй элемент массива (& a [1]), потому что первый элемент (a [0]) уже напечатан.

Что именно ты не понимаешь?

0 голосов
/ 24 марта 2011

Если вы можете убедиться в том, что следующий алгоритм работает для печати массива, вы должны понимать, почему работает код C, поскольку это прямой перевод.

Для печати n элементов массива:

  • Если вас попросили напечатать без элементов, просто остановитесь.
  • В противном случае:
    • Распечатать первый элемент, а затем
    • Вывести n-1 элементов остальной части массива (используя этот же рецепт).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...