Розглянемо стару, добре відому проблему :
У математиці найбільший спільний дільник (gcd)… з двох або більше ненульових цілих чисел - це найбільше додатне ціле число, яке ділить числа без залишку.
Визначення gcd напрочуд просте:
де mod - оператор модуля (тобто залишок після цілого поділу).
В англійській мові це визначення говорить, що найбільший спільний дільник будь-якого числа і нуля - це число, а найбільший спільний дільник двох чисел m і n - найбільший спільний дільник на n і решту після ділення m на n .
Якщо ви хочете знати, чому це працює, перегляньте статтю Вікіпедії про алгоритм Евкліда .
Давайте обчислимо gcd (10, 8) як приклад. Кожен крок дорівнює тому, що знаходиться безпосередньо перед ним:
- gcd (10, 8)
- gcd (10, 10 мод 8)
- gcd (8, 2)
- gcd (8, 8 мод 2)
- gcd (2, 0)
- 2
На першому кроці 8 не дорівнює нулю, тому застосовується друга частина визначення. 10 мод 8 = 2, оскільки 8 переходить у 10 один раз із залишком 2. На кроці 3 друга частина застосовується знову, але на цей раз 8 мод 2 = 0, оскільки 2 ділить 8 без залишку. На кроці 5 другий аргумент - 0, тому відповідь - 2.
Ви помітили, що gcd з’являється і з лівої, і з правої сторони знака рівності? Математик сказав, що це визначення є рекурсивним, оскільки вираз, який ви визначаєте, повторюється всередині його визначення.
Рекурсивні визначення, як правило, елегантні. Наприклад, рекурсивне визначення суми списку є
sum l =
if empty(l)
return 0
else
return head(l) + sum(tail(l))
де head
перший елемент у списку і tail
решта списку. Зауважимо, що sum
повторюється всередині його визначення наприкінці.
Можливо, ви бажаєте замість цього максимальне значення у списку:
max l =
if empty(l)
error
elsif length(l) = 1
return head(l)
else
tailmax = max(tail(l))
if head(l) > tailmax
return head(l)
else
return tailmax
Ви можете визначити множення невід'ємних цілих чисел рекурсивно, щоб перетворити його на ряд доповнень:
a * b =
if b = 0
return 0
else
return a + (a * (b - 1))
Якщо цей біт про перетворення множення на ряд доповнень не має сенсу, спробуйте розгорнути кілька простих прикладів, щоб побачити, як це працює.
Сортування сортування має прекрасне рекурсивне визначення:
sort(l) =
if empty(l) or length(l) = 1
return l
else
(left,right) = split l
return merge(sort(left), sort(right))
Рекурсивні визначення є навколо, якщо ви знаєте, що шукати. Зауважте, як усі ці визначення мають дуже прості базові випадки, наприклад , gcd (m, 0) = m. Рекурсивні випадки відхиляються від проблеми, щоб перейти до простих відповідей.
З таким розумінням тепер ви можете оцінити інші алгоритми у статті Вікіпедії про рекурсію !