Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Урок 8. Методы. Рекурсия.docx
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
81.07 Кб
Скачать

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 постройте. Напишите копии, опишите их и вы сможете хорошо для себя закрепить работу с рекурсией. Значит мы подошли к концу нашего урока. Те темы, которые мы с вами разбирали: перегрузка методов, разновидности аргументов, и дальше мы подошли к достаточно большому разделу - это к рекурсии. Я думаю, что рекурсия вам понятна после окончания этого урока, главное запомнить, что рекурсия строит некую копию метода и выполняется лесенкой. Сначала выполняются все первые половинки. Потом выполняются все вторые половинки. Мы разобрали понятие стека и поговорили много о чем интересном. На этом мы заканчиваем наш урок. Спасибо за внимание. До новых встреч.