Upgrade to Pro — share decks privately, control downloads, hide ads and more …

№ 2. Сложность алгоритмов, алгоритмы сортировки, рекурсивные алгоритмы

ОПК
February 15, 2021

№ 2. Сложность алгоритмов, алгоритмы сортировки, рекурсивные алгоритмы

1. Сложность алгоритмов. Нотация O, Ω, Θ.
2. Задача сортировки.
3. Bogosort и bozosort.
4. Сортировка выбором.
5. «Пузырьковая» сортировка.
6. Сортировка вставками.
7. Принцип «Разделяй и властвуй». Примеры: задача о ханойских башнях, получение перестановок, алгоритм Карацубы (умножение длинных чисел).
8. Основная теорема о рекуррентных соотношениях.
9. Поиск в массиве, двоичный поиск.
10. Рекурсия. Удачные и неудачные примеры использования рекурсии.

ОПК

February 15, 2021
Tweet

More Decks by ОПК

Other Decks in Programming

Transcript

  1. ВРЕМЕННАЯ СЛОЖНОСТЬ • Количество требуемых операций (время): 
 Q(n)=O(f(n)), где

    n – размер структуры данных . • f(n)=O(g(n)) ↔︎ 
 ∃ n0, M: ∀ n ≥ n0 
 |f(n)| ≤ M·|g(n)|. • O(1) – константная . • O(log n) – логарифмическая . • O(n) – линейная . • O(n log n) – квази-линейная . • O(n2) – квадратичная . • O(2n) – экспоненциальная.
  2. МАСШТАБИРУЕМОСТЬ n O(1) O(log n) O(n) O(n log n) O(n2) O(n3) 10

    A B C D E F 100 A 2B 10C 20D 100E 1000F 10000 A 4B 1000C 4000D 106∙E 109∙F
  3. О СКОРОСТИ И ТОРМОЗАХ Зависимость Время выполнения для n=1000 O(1)

    1 сек O(log n) 3 сек O(n) 2 мин O(n log n) 5 мин O(n2) 3 часа O(n3) 12 суток Для n=10 процесс выполняется 1 сек.
  4. О СКОРОСТИ И ТОРМОЗАХ • Для n=10 процесс выполняется: 


    1 сек . • Для n=100 процесс выполняется: 
 1027 сек. ≈ 4⋅1019 ле т • Для n=1000 процесс выполняется: 
 10298 сек. ≈ 3⋅10290 лет Экспоненциальная сложность 
 Q(n)=O(2n)
  5. ПРИМЕРЫ • Вычисление суммы двух чисел – O(1) 
 (хотя

    на самом деле зависит от размера чисел) . • Подсчет длины строки – O(n) 
 (один цикл) . • Умножение двух матриц – O(n3) 
 (три вложенных цикла) . • Полный перебор всех n-битных чисел – O(2n).
  6. O, Ω, Θ • f(n)=O(g(n)) ⇔ ∃ n0, M ∀

    n ≥ n0: |f(n)| ≤ M·|g(n)| • f(n)=Ω(g(n)) ⇔ ∃ n0, M ∀ n ≥ n0: |f(n)| ≥ M·|g(n)| • f(n)=Θ(g(n)) ⇔ ∃ n0, M1, M2 ∀ n ≥ n0: M1 ·|g(n)| ≤ |f(n)| ≤ M2 ·|g(n)|.
  7. СЛУЧАИ • Сложность в … • в лучшем случае (best-case

    ) • в среднем случае (average-case ) • в худшем случае (worst-case) (вариант по умолчанию) • best-case ≤ average-case ≤ worst-case
  8. ЗАДАЧА СОРТИРОВКИ • Записи R1, R2, …, Rn . •

    Ключи K1, K2, …, Kn . • Требуется расставить записи так, чтобы ключи шли в неубывающем порядке.
  9. ИДИОТСКАЯ СОРТИРОВКА (BOGOSORT) 1. Проверить, является ли массив уже отсортированным.

    Если да, то алгоритм завершается . 2. Случайным образом перемешать записи в массиве и перейти к шагу 1. в среднем: O(n·n!)
  10. ТУПАЯ СОРТИРОВКА (BOZOSORT) 1. Проверить, является ли массив уже отсортированным.

    Если да, то алгоритм завершается . 2. Случайным образом поменять местами две записи в массиве и перейти к шагу 1. в среднем: O(n!)
  11. СОРТИРОВКА ВЫБОРОМ (SELECTION SORT) 1. На j-ой итерации первые (j

    – 1) элементов уже на своих местах . 2. Найти наименьший ключ Km из Kj, Kj+1, …, Kn . 3. Поменять местами Rj и Rm. 
 Тогда первые j элементов на своих местах . 4. Если j равен n, то массив отсортирован, иначе переходим на шаг 1. O(n2)
  12. «ПУЗЫРЬКОВАЯ» СОРТИРОВКА (BUBBLE SORT) 1. Пройти массив от начала к

    концу, сравнивая на каждом шаге пару соседних ключей Ki и Ki+1. Если Ki > Ki+1, то записи Ri и Ri+1 меняются местами . 2. Если на предыдущем шаге была хотя бы одна перестановка, перейти к шагу 1. 
 В противном случае — конец, массив отсортирован . Бонус: чередовать проходы в прямую и обратную стороны (cocktail sort). O(n2)
  13. «ПУЗЫРЬКОВАЯ» СОРТИРОВКА (BUBBLE SORT) * анимация для версии сортировки, которая

    проверяет в обратную сторону http://www.sorting-algorithms.com/bubble-sort
  14. СОРТИРОВКА ВСТАВКАМИ (INSERTION SORT) 1. На j-ой итерации часть записей

    уже отсортирована: 
 K1 ≤ K2 ≤ … ≤ Kj−1, 1 < j ≤ n. 2. Меняем Rj с элементами слева от него, пока не встретим элемент, меньший Kj. После этого последовательность R1, R2, …, Rj отсортирована . 3. Если j равен n, то массив отсортирован, иначе переходим на шаг 1. O(n2)
  15. «РАЗДЕЛЯЙ И ВЛАСТВУЙ» • Разделение задачи на несколько подзадач .

    • Покорение: решение подзадач . • Комбинирование решения исходной задачи из решений подзадач.
  16. ЗАДАЧА О ХАНОЙСКОЙ БАШНЕ • Задача: перенести n дисков с

    палки 1 на палку 3, используя палку 2 как свободную . • Можно класть только меньший диск на больший!
  17. РЕШЕНИЕ 1. Перенести n−1 дисков c 1 на 2, пользуясь

    свободной 3 . 2. Перенести самый большой (n-й по счету) диск с 1 на 3 . 3. Перенести n−1 дисков c 2 на 3, пользуясь свободной 1.
  18. ПОЛУЧЕНИЕ ВСЕХ ПЕРЕСТАНОВОК Как получить все перестановки чисел 1…n ?

    1. Как-то получаем все перестановки 1…n−1 . 2. Есть n способов добавить число n к каждой из перестановок, полученных на шаге 1.
  19. АЛГОРИТМ КАРАЦУБЫ ДЛЯ УМНОЖЕНИЯ ДЛИННЫХ ЧИСЕЛ Есть два длинных числа:

    a2n a2n−1 … a1 и b2n b2n−1 … b1. Нужно получить произведение . C = (102n a2n + 102n−1 a2n−1 +…+ a1) × 
 (102n b2n +102n−1 b2n−1 +…+ b1) C = (10n A1+A0)×(10n B1+B0) = 
 102n A1B1 + 10n (A1B0+B1A0) + A0B0, 
 где A1 = 10n a2n + 10n−1 a2n−1 +…+ an+1, 
 A0 = 10n an + 10n−1 an−1 +…+ a1, 
 B0, B1 – аналогично.
  20. АЛГОРИТМ КАРАЦУБЫ ДЛЯ УМНОЖЕНИЯ ДЛИННЫХ ЧИСЕЛ Умножение чисел размерности 2n

    сведено к четырем умножениям n-размерных чисел и комбинированию посредством сдвигов и сложений . Хитрость! Вычисляем 3 умножения: 
 D1 = A0B0, 
 D2 = A1B1, 
 D3 = (A0 + A1)(B0 + B1) . Тогда C = (102n D2 + 10n (D3−D2−D1) + D1).
  21. ОСНОВНАЯ ТЕОРЕМА О РЕКУРРЕНТНЫХ СООТНОШЕНИЯ Х (THE MASTER METHOD) Пусть

    T(n) = a T(n/b) + O(nd), a ≥ 1, b ≥ 2, d ≥ 0 количество подзадач размер каждой подзадачи сложность разделения и объединения T(n) = O(nd log n) , T(n) = O(nd) , T(n) = O(nlog a / log b), если a = b d если a < bd если a > bd
  22. ПРИМЕРЫ РЕКУРРЕНТНЫХ СООТНОШЕНИЙ • Прямолинейное умножение длинных чисел: 
 T(n)

    = 4 T(n/2) + O(n) → T(n) = O(nlog 4 / log 2) = O(n2) • Алгоритм Карацубы: 
 T(n) = 3 T(n/2) + O(n) → T(n) = O(nlog 3 / log 2) ≈ O(n1,58)
  23. ЛИНЕЙНЫЙ ПОИСК Дан массив A длины n и ключ K.

    Требуется определить положение элемента с данным ключом в массиве или установить, что его там нет . Последовательно сравниваем ключи, пока не найдем совпадающий ключ или массив не кончится . Сложность: O(n).
  24. ДВОИЧНЫЙ ПОИСК Дан отсортированный массив A длины n и ключ

    K. Двоичный поиск (он же бинарный поиск, он же поиск делением пополам) : Возьмем серединный элемент массива (m-й) и сравним его ключ Km с K : • Если Km = K, то ключ найден . • Если Km < K, то продолжаем поиск в правой половине: A[m+1…n−1] . • Если Km > K, то продолжаем поиск в левой половине: A[0…m−1] . Сложность: T(n) = T(n/2) + O(1) = O(log n).
  25. РЕКУРСИЯ • Рекурсия — см. рекурсия . • Рекурсия —

    вызов функцией самой себя . • Есть опасность бесконечной рекурсии . • В большинстве случаев расходуется машинный стек . • Взаимодействие только через аргументы и возвращаемое значение . • Реализация может быть итеративной (своя реализация стека или оптимизация хвостовой рекурсии).