- •28: Console.ReadKey();
- •29: Static void Main()
- •36: // Delay.
- •37: Console.ReadKey();
- •34: // Delay.
- •35: Console.ReadKey();
- •1: Using System;
- •1: Using System;
- •9: Namespace Methods
- •11: Class Program
- •28: // Delay.
- •29: Console.ReadKey();
- •1: Using System;
- •8: Namespace Methods
- •10: Class Program
- •24: Static void Main()
- •28: // Delay.
- •29: Console.ReadKey();
- •1: Using System;
- •7: Namespace Methods
- •9: Class Program
- •32: Static void Main()
- •36: // Delay.
- •37: Console.ReadKey();
1: Using System;
2:
3: // Рекурсия (сложная рекурсия).
4:
5: // Сложная рекурсия - вызов методом себя, через другой метод.
6:
7: Namespace Methods
8: {
9: Class Program
10: {
11: static void Recursion(int counter)
12: {
13: counter--;
14:
15: Console.WriteLine("Первая половина метода Recursion: {0}", counter);
16:
17: if (counter != 0)
18: Method(counter);
19:
20: Console.WriteLine("Вторая половина метода Recursion: {0}", counter);
21: }
22:
23: static void Method(int counter)
24: {
25: Console.WriteLine("Первая половина метода Method: {0}", counter);
26:
27: Recursion(counter);
28:
29: Console.WriteLine("Вторая половина метода Method: {0}", counter);
30: }
31:
32: Static void Main()
33: {
34: Method(3);
35:
36: // Delay.
37: Console.ReadKey();
38: }
39: }
40: }
На 11 строке мы создаем метод Recursion, снова же тот же самый counter, но в условной конструкции if, если условие удовлетворяет истинности мы уже вызываем другой метод. А этот метод уже безусловно вызывает наш метод, он вызывает нас. Вы видите да? И получается, что здесь мы вызываем вот этот вот метод из нашего рекурсивного метода. А он будет перевызывать нас. Видите как идет здесь вызов. Давайте попробуем пошагать эту программу. Мы вызываем метод 3 раза, вот у нас идет Method(3). Мы переходим в метод. Count = 3. Отработала первая половина метода, вызывается метод Recursion. Здесь мы уменьшаем счетчик на 1 и снова же вызываем вот этот метод. А он снова же вызывает нас. Мы снова же вызываем его, а он вызывает нас. Мы снова вызываем этот метод. А он вызывает нас. То есть теперь мы пошли выполнять вторые части этих методов видите? И если мы посмотрим в код, то сначала видим, что отработала первая половина метода Method. Потом первая половина метода Recursion, потом первая половина метода Method и т.д. А потом идут дорабатывать вторые половинки. Вот эта техника называется сложной рекурсией, когда мы вызываем себя через другой метод. Видите, самовызов через другой метод. Думаю что с рекурсией мы достаточно разобрались, мы еще будем возвращаться к этому понятию, еще будем с ним работать. А мы идем с вами дальше. И мы уже подходим к окончанию нашего урока. И под конец мы рассмотрим три маленьких примера использования рекурсии. Обратите внимание, этот первый пример показывает нам вывод числа в двоичном формате, которое мы передаем в десятичном формате. Вот например у нас имеется число в десятичном формате 12. Как это число выглядит в 16-ричном формате? Это С = 1100. Вот это число, как оно у нас выведется. Давайте выполнимся.
1: using System;
2:
3: // Вывод в двоичном формате числа, переданного в десятичном формате
4:
5: namespace BinaryDigit
6: {
7: class Program
8: {
9: static void Converter(int n)
10: {
11: int temp;
12:
13: temp = n % 2;
14:
15: if (n >= 2)
16: Converter(n / 2);
17:
18: Console.Write(temp);
19: }
20:
21: static void Main()
22: {
23: int n = 69;
24:
25: Converter(n);
26:
27: Console.ReadKey();
28: }
29: }
30: }
Обратите внимание, вот, мы десятичное число 12 преобразовали в двоичный формат, при этом… Давайте сейчас попробуем пошагать. Вот у нас происходит вызов метода Converter. Значит n = 12. Смотрим, остаток равен 0. N больше либо равно 2. Да. Что сейчас произойдет? Построится копия. А вы помните формулы перевода чисел из десятичного формата в двоичный, помните польскую запись числа. Мы рассматривали ее на машинной математике. Если вы откроете этот пример, сосредоточитесь на нем, пошагаете, то вы здесь ясно увидите работу рекурсии. И мы здесь давайте уже дошагаем. Мы здесь шагаем первую половину метода, теперь переходим выводить остатки. А как мы остатки выведем? В обратной записи. Помните польскую запись числа. Польская нотация. Обратный вывод. Мы вот так вот делили, а потом из остатков получали число. И мы здесь сейчас можем посмотреть, сейчас должно вывестись. Смотрите, у нас вывелась первая единица с последней копии. Еще одна единица вывелась. Сейчас у нас выведется что? 0. И последний ноль остался в оригинале и вот мы его получили. Здесь вам нужно сосредоточиться взять этот пример, пошагать, посмотреть пример из машинной математикой и посмотреть как работает польская запись числа. То есть мы взяли и вот так рекурсивно преобразовали десятичное число в двоичное. Еще какие способы есть использования рекурсии.
1: using System;
2:
3: // Нахождение наибольшего общего делителя (НОД) двух целых чисел
4:
5: namespace Recursion
6: {
7: class Program
8: {
9: static int Calculate(int a, int b)
10: {
11: if (a % b == 0)
12: return b;
13: else
14: return Calculate(b, a % b);
15: }
16:
17: static void Main()
18: {
19: Console.WriteLine("Нахождение наибольшего общего делителя двух целых чисел");
20:
21: int a = 15, b = 33;
22:
23: Console.WriteLine("a = {0}, b = {1}, НОД = {2};", a, b, Calculate(a, b));
24:
25: Console.ReadKey();
26: }
27:
28: #region Второй вариант решения
29:
30: static int Calculate2(int a, int b)
31: {
32: while (b != 0)
33: b = a % (a = b);
34: return a;
35: }
36:
37: #endregion
38: }
39: }
Ага, нахождение наибольшего общего делителя двух целых чисел. Что такое НОД. Помните, мы в школе учили это понятие. Наибольшим общим делителем для двух целый чисел m и n называется наибольший из их общих делителей. Например для чисел 70 и 105 наибольший общий делитель равен 35. Числа большего, чем 35 у нас не имеется. И название идет не просто общий делитель. Потому что общий делитель для 70 и 105 например 5. А именно наибольший общий делитель. Так вот, для изыскания НОДа мы тоже можем использовать рекурсию в функциях. Обратите внимание, здесь идет первый способ решения этой задачи и второй способ решения этой задачи. Один и второй. Я вам рекомендую ее тоже пошагать этот пример и поизучать его. Открыть вот эту страницу на Википедии посмотреть что же такое НОД и согласно вот этих формул попробовать пошагать. Еще где может использоваться давайте посмотрим. Скорее всего это факториал. Давайте смотрим. Здесь у нас идет расчет факториала.
1: using System;
2:
3: // Нахождение факториала числа.
4:
5: namespace MethodsRecFact
6: {
7:
8: class Program
9: {
10: static int Factorial(int n)
11: {
12: if (n == 0)
13: return 1;
14: else
15: return n * Factorial(n - 1);
16: }
17:
18: static void Main()
19: {
20: int factorial = Factorial(5);
21:
22: Console.WriteLine(factorial);
23:
24: // Задержка.
25: Console.ReadKey();
26: }
27: }
28: }
До этот мы рассчитывали факториал с помощью циклов do-while. И факториал… Помните это понятие? Что мы там находили? Мы находили возможное количество вариаций доставки книги. Также здесь, только мы уже не используем цикл, а используем также рекурсию. И соответственно в копиях будут сохранятся промежуточные вычисления значений факториала. Потому что мы знаем, что если мы хотим вычислить 4! = 24. Мы понимаем, что мы начнем разбивать ряд на копии, и натуральный ряд чисел до 4 будет разбит по каждой из копий рекурсивно вызванных методов ну и дальше произойдет на возврате, мы будем n умножать на возвращаемое значение из построенной копии. Пошагайте. Попробуйте разрисовать эти программы так же как мы разрисовывали вот так лесенко с использованием копий на небольших числа. Тот же факториал 4 постройте. Напишите копии, опишите их и вы сможете хорошо для себя закрепить работу с рекурсией. Значит мы подошли к концу нашего урока. Те темы, которые мы с вами разбирали: перегрузка методов, разновидности аргументов, и дальше мы подошли к достаточно большому разделу - это к рекурсии. Я думаю, что рекурсия вам понятна после окончания этого урока, главное запомнить, что рекурсия строит некую копию метода и выполняется лесенкой. Сначала выполняются все первые половинки. Потом выполняются все вторые половинки. Мы разобрали понятие стека и поговорили много о чем интересном. На этом мы заканчиваем наш урок. Спасибо за внимание. До новых встреч.
