Выбрать главу

class Factorial {

// Это рекурсивный метод, public int FactR(int n) { int result;

if(n==l) return 1; result = FactR(n-l) * n; return result;

}

// Это итерационный метод, public int FactI(int n) { int t, result;

result = 1;

for(t=l; t <= n; t++) result *= t; return result;

class Recursion {

static void Main() { Factorial f = new

Factorial ();

Console.WriteLine("Факториалы, рассчитанные рекурсивным методом. Console.WriteLine("Факториал числа    3    равен    "    +    f.FactR(3));

Факториал числа    4    равен    "    +    f.FactR(4));

Console.WriteLine( Console.WriteLine(

Факториал числа    5    равен    "    +    f.FactR(5));

Console.WriteLine() ;

Console.WriteLine("Факториалы, рассчитанные итерационным методом Console.WriteLine("Факториал    числа    3    равен    "    +    f.FactR(3));

• Console.WriteLine("Факториал    числа    4    равен    "    +    f.FactR(4));

Console.WriteLine("Факториал    числа    5    равен    "    +    f.FactR(5));

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

Факториалы, рассчитанные рекурсивным методом.

Факториал числа 3 равен 6 Факториал числа 4 равен 24 Факториал числа 5 равен 120

Факториалы, рассчитанные итерационным методом.

Принцип действия нерекурсивного метода FactI () вполне очевиден. В нем используется цикл, в котором числа, начиная с 1, последовательно умножаются друг на друга, постепенно образуя произведение, дающее факториал.

А рекурсивный метод FactR () действует по более сложному принципу. Если метод FactR () вызывается с аргументом 1, то он возвращает значение 1. В противном случае он возвращает произведение FactR (п-1) *п. Для вычисления этого произведения метод FactR () вызывается с аргументом п-1. Этот процесс повторяется до тех пор, пока значение аргумента п не станет равным 1, после чего из предыдущих вызовов данного метода начнут возвращаться полученные значения. Например, когда вычисляется факториал числа 2, то при первом вызове метода FactR () происходит второй его вызов с аргументом 1. Из этого вызова возвращается значение 1, которое затем умножается на 2 (первоначальное значение аргумента п). В итоге возвращается результат 2, равный факториалу числа 2 (1x2). Было бы любопытно ввести в метод FactR () операторы, содержащие вызовы метода WriteLineO, чтобы наглядно показать уровень рекурсии при каждом вызове метода FactR (), а также вывести промежуточные результаты вычисления факториала заданного числа.

Когда метод вызывает самого себя, в системном стеке распределяется память для новых локальных переменных и параметров, и код метода выполняется с этими новыми переменными и параметрами с самого начала. При рекурсивном вызове метода не создается его новая копия, а лишь используются его новые аргументы. А при возврате из каждого рекурсивного вызова старые локальные переменные и параметры извлекаются из стека, и выполнение возобновляется с точки вызова в методе. Рекурсивные методы можно сравнить по принципу действия с постепенно сжимающейся и затем распрямляющейся пружиной.

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

DisplayRev().

// Вывести символьную строку в обратном порядке, используя рекурсию.

using System;

class RevStr {

// Вывести символьную строку в обратном порядке, public void DisplayRev(string str) { if (str.Length > 0)

DisplayRev(str.Substring(1, str.Length-1)); else

return;

Console.Write(str[0]);

}

}

class RevStrDemo { static void Main() {

string s = "Это тест";    ,

RevStr rsOb = new RevStr ();

Console.WriteLine("Исходная строка: " + s);

Console.Write("Перевернутая строка: "); rsOb.DisplayRev(sf;

Console.WriteLine();

}

}

Вот к какому результату приводит выполнение этого кода.

Исходная строка: Это тест Перевернутая строка: тсет отЭ

Всякий раз, когда вызывается метод DisplayRev (), в нем происходит проверка длины символьной строки, представленной аргументом str. Если длина строки не равна нулю, то метод DisplayRev () вызывается рекурсивно с новой строкой, которая меньше исходной строки на один символ. Этот процесс повторяется до тех пор, пока данному методу не будет передана строка нулевой длины. После этого начнется раскручиваться в обратном порядке механизм всех рекурсивных вызовов метода DisplayRev (). При возврате из каждого такого вызова выводится первый символ строки, представленной аргументом s t г, а в итоге вся строка выводится в обратном порядке.