Помощь в написании студенческих работ
Антистрессовый сервис

Рекурсивные методы. 
Программирование. 
Базовый курс с#

РефератПомощь в написанииУзнать стоимостьмоей работы

В нашем примере условием выхода из цепочки рекурсивных вызовов является истинность выражения (k == 0| |к == 1). Так как значение к конечно и параметр при каждом следующем вызове уменьшается на 1, то цепочка самовызовов конечна. Идя от конца цепочки, т. е. от 1 ! = 1, к началу, можно убедиться, что все вызовы работают верно и метод работает правильно. Первый параметр метода char ch — ссылка… Читать ещё >

Рекурсивные методы. Программирование. Базовый курс с# (реферат, курсовая, диплом, контрольная)

Рекурсивным называют метод, который прямо (непосредственно) или косвенно вызывает самого себя. Метод называют косвенно рекурсивным, если он содержит обращение к другому методу, содержащему прямой или косвенный вызов определяемого (первого) метода. В случае косвенной рекурсивности по тексту определения метода его рекурсивность может быть не видна. Если в теле метода явно используется обращение к этому методу, то имеет место прямая рекурсия. В этом случае говорят, что метод самовызывающий (self-calling). Именно самовызывающие методы будем называть рекурсивными, а для методов с косвенной рекурсией будем использовать термин «косвенно рекурсивные методы».

Классический пример рекурсивного метода — функция для вычисления факториала неотрицательного целого числа. На языке C# ее можно записать таким образом:

static long fact (int k).

{

if (k < 0) return 0;

if (к == 0 || к == 1) return 1; return к * fact (k — 1);

}

Для отрицательного аргумента результат (по определению факториала) не существует. В этом случае функция возвращает нулевое значение (можно было бы возвращать, например, отрицательное значение). Для нулевого и единичного аргумента, по определению факториала, возвращаемое значение равно 1. Если k > 1, то вызывается та же функция с уменьшенным на 1 значением аргумента и возвращаемое ею значение умножается на текущее значение аргумента к. Тем самым организуется вычисление произведения 1*2*3*…*-2)* (к — 1) * к.

При проектировании рекурсивного метода нужно убедиться:

  • — что он может завершить работу, т. е. невозможно возникновение зацикливания;
  • — что метод приводит к получению правильных результатов.

Для удовлетворения первого требования должны соблюдаться два правила:

  • 1) в последовательности рекурсивных вызовов должен быть явный разрыв, т. е. самовызовы должны выполняться до тех пор, пока истинно значение некоторого выражения, операнды которого изменяются от вызова к вызову;
  • 2) при самовызовах должны происходить изменения параметров и эти изменения после конечного числа вызовов должны привести к нарушению проверяемого условия из пункта 1.

В нашем примере условием выхода из цепочки рекурсивных вызовов является истинность выражения (k == 0| |к == 1). Так как значение к конечно и параметр при каждом следующем вызове уменьшается на 1, то цепочка самовызовов конечна. Идя от конца цепочки, т. е. от 1 ! = 1, к началу, можно убедиться, что все вызовы работают верно и метод работает правильно.

Иллюстрация цепочки самовызовов для метода вычисления факториала:

Рекурсивные методы. Программирование. Базовый курс с#.

Эффективность рекурсивного метода зачастую определяется глубиной рекурсии, т. е. количеством самовызовов в одной цепочке при обращении к методу.

В качестве еще одного примера рекурсии приведем метод, преобразующий все цифры натурального числа в соответствующие им символы. Параметр метода — целое число типа int, результат — массив char[]. Код метода:

// Цифры натурального числа: static char[] arNumbs (int n).

{

if (n / 10 == 0).

{ return new char[] { (char)(n + (int)'0') }; }.

else.

{

char[] res = arNumbs (n / 10); int L = res. Length;

Array.Resize (ref res, L + 1); res[L] = (char)((n % 10) + (int)'0‘); return res;

} }

В коде метода arNumbs (int n) первый шаг — проверка результата целочисленного деления значения параметра на 10. Если результат нулевой, то значение параметра — число меньшее 10 и представлено одной цифрой. В этом случае в операторе возврата из метода создается символьный массив из одного элемента со значением, равным символьному представлению значения параметра (одной цифры). Ссылка на массив из одного элемента — это результат, возвращаемый методом при прерывании цепочки рекурсивных самовызовов.

В более общем случае параметр больше 10 и выполняется блок операторов, размещенных в ветви else. Объявляется ссылка char [] res, которой присваивается результат рекурсивного обращения к методу arNumbs (n/10). Для полученного из этого метода массива вычисляется размер (свойство res. Length). Затем метод Array. ResizeO увеличивает на 1 размер массива, связанного со ссылкой res. В последний элемент нового массива заносится символьное представление последней цифры значения параметра. Ссылка на полученный массив возвращается как результат рекурсивного вызова.

Для иллюстрации выполнения метода используем следующий код:

static void MainQ.

{

foreach (var c in arNumbs (90 580)).

Console.Write (c + ««);

}

Результат выполнения программы:

9 0 5 8 0.

Цепочка рекурсивных вызовов для приведенного кода:

arNumbs (90 580) -> arNumbs (9 058) -> arNumbs (905) -> arNumbs (0090) -> arNumbs (009) -> разрыв цепочки.

Цепочка возвратов из самовызовов:

res[0] = '9' -> res[l] = '0' -> res[2] = '5' -> res[3] = '8' -> res[4] = '0'.

Многие задачи, требующие циклического повторения операций, могут быть представлены как рекурсивными, так и итерационными алгоритмами. Основной для рекурсивного алгоритма является его самовызов, а для итерационного алгоритма — цикл.

В качестве иллюстрации замены цикла на рекурсию приведем рекурсивный метод (процедуру) для вывода на консольный экран значений значимых элементов символьного массива. Пусть в массиве только начальные элементы имеют значимые значения, а элементам, расположенным за ними (до конца массива), присвоены умалчиваемые значения. Напомним, что при создании символьного массива без явной инициализации его элементам по умолчанию присваиваются значения ''.

Параметры метода — ссылка на одномерный символьный массив и индекс первого выводимого элемента. Окончание вывода — конец массива либо терминальный символ '' в качестве значения очередного элемента.

// Рекурсивный метод печати элементов символьного массива static void chPrint (char[] ch, int beg).

{

if (beg >= ch. Length-1 || ch[beg] == '').

{

Console.WriteLine (); return;

}

Console.Write (ch[beg] + ««);

chPrint (ch, beg + 1);

}

Первый параметр метода char[] ch — ссылка на обрабатываемый символьный массив. Второй параметр int beg — индекс элемента, начиная с которого выводятся значения. Условие выхода из метода — достижение конца массива beg > = ch. Length-1 или значение '' элемента с индексом beg. Если условие выхода не достигнуто, выполняются операторы:

Console.Write (ch[beg] + ««); chPrint (ch, beg + 1);

Тем самым первым выводится значение начального элемента массива и происходит самовызов метода для следующего значения второго параметра, и т. д…

Вызов последнего отличного от '' элемента или достижение конца массива завершает цепочку рекурсивных обращений.

Пример использования приведенного метода (0917.cs):

static void MainQ.

{

int size = 9;

char[] simbols = new char[size];

string line = «AaBbCc» ;

for (int к = 0; к < line. Length; k++) simbols[k] = line[k]; chPrint (simbols, 0);

}

Результат выполнения программы:

A a в b С с Обратите внимание, что при обращении к методу chPrint () второй аргумент равен 0, т. е. вывод идет с начала массива.

Показать весь текст
Заполнить форму текущей работой