Презентация для JuJa вебинара о том, как писать рекурсивные программы с примером о вычислении факториала и чисел Фибоначчи. Также рассказывается о поиске линейном, бинарном, в глубину и в ширину, как работает поисковая система.
Презентация сделана для новичков в деле программистов.
3. Рекурсия это
– замкнутый круг, мы обречены на повторение тех же
действий, но с той разницей, что входные данный можно
менять!
4. Рекурсия без шуточек
Рекурсия это решение задачи с помощью решения ее
маленьких подзадач, структура которых повторяет
структуру задачи.
Пример: вычисление факториала
0! = 1
1! = 1 =1 ⋅ 1 = 1 ⋅ 0!
2! = 2 = 2 ⋅ 1 ⋅ 1 = 2 ⋅ 1!
3! = 6 = 3 ⋅ 2 ⋅ 1 ⋅ 1 = 3 ⋅ 2!
4! = 24 = 4 ⋅ 3 ⋅ 2 ⋅ 1 ⋅ 1 = 4 ⋅ 3!
На практике это выглядит как вызов методом самого же
себя, но с другими параметрами.
6. Основные
характеристики рекурсии
1. Терминальная ветвь - часть метода или метод с
условием, которое прервет цепочку рекурсивных
вызовов и возвратит правильный результат.
Должна быть в каждой рекурсии минимум одна и
достижима за конечное число рекурсивных вызовов.
2. Глубина рекурсии - количество раз вызова
функцией себя же или аналогичной.
7. Число Эйлера
e ≈ 2,71828
Константу впервые вычислил швейцарский математик Якоб Бернулли в
ходе решения задачи о предельной величине процентного дохода.
Если исходная сумма $1 и начисляется 100% годовых один раз в конце
года, то итоговая сумма будет $2.
А если такой же процент разбить на несколько начислений, то
результирующий доход можно представить следующим образом:
8. Рекурсия в банке
Начисляется
100% на $1
Количество
начислений
за год
Начисляем ту же
прибыль несколько
раз в год
Результирующая
сумма
Начисляем в
конце года 100%
1 $1 * 200% = $1 * 2 = $2 $2
100% разбиты на
2 увеличения
2
$1 * 150% ^2 = $1 *
1.5^2 = $2.25
$2.25
100% разбиты на
квартальные
увеличения
4 $2.44
Начисляем так
часто, как клиент
пожелает
n ≈ $2.71828
9. Еще раз о факториале
• Смысл факториала - определить количество
перестановок или упорядочиваний множества из
n элементов.
Пример: n = 3, а именно A B C
1) A B C
2) A C B
3) B A C 3! =1 * 2 * 3 = 6
4) B C A
5) С A B
6) C B A
10. Факториал через цикл
public class Factorial {
public static void main(String[] args) {
int result = factorialCycle(3);
System.out.println(result);
}
private static int factorialCycle(int n) {
int factorial = 1;
for (int i = 1; i <= n; i++) {
factorial *= i;
}
return factorial;
}
}
11. Факториал через
рекурсию
public class Factorial {
public static void main(String[] args) {
int result = factorialRecursion(2);
System.out.println(result);
}
private static int factorialRecursion(int n) {
if (n > 1) {
return n * factorialRecursion(n - 1);
}
return 1;
}
}
12. Параллельная рекурсия
• Несколько функций вычисляются
и параллельно и рекурсивно.
Пример: числа Фибоначчи
Каждое следующее число равно сумме 2х предыдущих
Происхождение: Фибоначчи рассматривает развитие
идеализированной (биологически нереальной) популяции
кроликов, предполагая, что: изначально есть новорожденная
пара кроликов (самец и самка); со второго месяца после
своего рождения кролики начинают спариваться и каждый
месяц производить новую пару кроликов; кролики никогда
не умирают. Сколько пар кроликов будет через год?
13. Числа Фибоначчи
public class FibonachiNumbers {
public static void main(String[] args) {
int n = 6;
int result = fibonachi(n);
System.out.println(result);
}
private static int fibonachi(int n) {
//1, 1, 2, 3, 5, 8
if (n > 2){
return fibonachi(n - 1) + fibonachi(n - 2);
}
return 1;
}
}
14. Хвостовая рекурсия
• Хвостовая рекурсия — частный случай рекурсии,
при котором любой рекурсивный вызов является
последней операцией перед возвратом из функции.
Всегда легко может быть заменен на итерацию.
15. Еще пример рекурсии
• Способ хранения данных: связный список
• Множественная рекурсия (вызов не только одной
рекурсивной функции) - обход дерева в глубину
• Непрямая рекурсия - 2 зеркала напротив друг-друга,
класс А обращается к классу В, который вызывает
класс А.
16. За и против рекурсии,
выводы
✓Запись алгоритма может выглядеть проще, нагляднее и
понятнее
- Чревато загромождением памяти, ведь надо помнить все
предыдущие действия, чтоб идти по рекурсии.
๏ Используйте рекурсию для программ, где не будет
возникать слишком большой глубины рекурсии и
желательно для изначально рекурсивных алгоритмов.
18. Как можно искать:
Линейный поиск
Как работает: Перебор в лоб.
Главный плюс - понятно, как работает.
Не надо заранее готовить данные
Главный минус - медленно.
Особенность: в случае повторяемых значений найдет
первое
19. Линейный поиск
public static void main(String[] args) {
int[] arr = {1, 15, 8, 2, 15, 19}; // где ищем
int x = 8; // что ищем
int i = linearSearch(arr, x);
System.out.println(i);
}
public static int linearSearch(int[] arr, int x){
for (int i = 0; i < arr.length; i++) {
int element = arr[i];
if (element == x){
return i;
}
}
return -1;
}
20. Как лучше искать:
бинарный поиск
Как работает: сравнивает серединный элемент
отсортированного массива со значением, которое ищет.
Ориентируясь, где может находится нужное значение, берет
нужную часть и повторяет те же действия пока не найдет.
Или вернет ближайший индекс с минусом в случае
отсутствия элемента.
Плюс в скорости, трудоемкость
Минус в необходимости подготовить данные, что тоже
имеет трудоемкость.
Особенность: в случае повторяемых значений найдет
непонятное
22. Реализация бинарного
поиска
public class BinarySearch {
/**
* ищем индекс элемента в массиве
* или возвращаем -1, если элемента нету
*/
public static void main(String[] args) {
int[] arr = {1, 5, 8, 12, 15, 19}; // где ищем
int x = 15; // что ищем
int i = binarySearch(arr, x, 0, arr.length - 1);
System.out.println(i);
}
public static int binarySearch(int[] arr, int x, int low, int high) {
if (high < low) {
return -1; //не найдено
}
int mid = (low + high) / 2;
if (arr[mid] > x) {
//ищем в нижней части массива
return binarySearch(arr, x, low, mid - 1);
} else if (arr[mid] < x) {
//ищем в верхней части массива
return binarySearch(arr, x, mid + 1, high);
} else return mid; //найденный элемент
}
}
23. • Дерево является основой для хранения некоторых
структур данных, например дерева рода и для других
задач, где важен порядок элементов и их место, т. к.
какой соцгруппе первой давать субсидию.
• В некоторых языках программирования дерево -
основа ассоциативного массива (мапы), позволяющего
хранить пары вида «(ключ, значение)» и
поддерживающий операции добавления пары, а также
поиска и удаления пары по ключу. В стандартной
библиотеке STL языка С++ контейнер map реализован
на основе красно-чёрного дерева.
Зачем нужны деревья?
24. Поиск по хешу
• Хеш-функция - некая функция, которая на основе значения
элемента строит число. Для разных элементов число
должно быть разным, а для одинаковых - одинаковым.
Создана с целью упорядочивания элементов в массиве
данных, для ускорения поиска, ведь сравнивать числа
легко. Альтернатива дереву.
Хэш-таблицы плохи тем, что на их основе нельзя
реализовать быстро работающие дополнительные операции
MIN, MAX и алгоритм обхода всех хранимых пар в порядке
возрастания или убывания ключей.
25. Поиск в ширину
• Это обход по узлам дерева в
зависимости от их уровня.
Пример: поиск, сколько тегов/узлов
«hotel» имеется в xml документе.
26. Поиск в глубину
• Представляет собой обход
дерева по всей ветке до
последнего листочка, только
потом переход на следующую
ветку/подветку
Пример: Обход лабиринта.
27. Как работает поисковик?
1. При появлении нового ресурса она добавляется в
базу и ей приваривается поисковой индекс.
2. Странице присваивается ранг/аппетитность.
3. При вводе поискового запроса используется
словарь похожих терминов и с помощью индексов
поисковик предлагает результаты.
http://lmgtfy.com/?q=how+search+engine+works
28. Как меня найти
• Facebook: https://www.facebook.com/
olexandra.dmytrenko
• Twitter: https://twitter.com/LadyInIT
• Google+: https://plus.google.com/
104080342212951796546
• Linkedin: https://www.linkedin.com/in/olexandra-
dmytrenko-078a0330/