Глава 1 Роль алгоритмов в вычислениях

Алгоритмы как технология

Раздел 1.2 · Мысленный эксперимент

Представим бесконечно быстрый компьютер

…и бесконечную память в придачу. Нужно ли было бы тогда вообще изучать алгоритмы?

∞

Скорость

Любой метод с конечным числом шагов отрабатывает мгновенно — неважно, сколько этих шагов.

∞

Память

Храним что угодно и сколько угодно — экономить нечего и незачем.

Нужно — но только чтобы показать, что метод завершается за конечное время и даёт правильный ответ. Подошёл бы любой корректный метод. Скорее всего, выбирали бы тот, что легче всего реализовать, — в лучшем случае ещё и в хороших традициях программирования: аккуратно написанный и задокументированный.
Раздел 1.2 · Возвращаемся в реальность

Время — такой же ограниченный ресурс, как память

скорость < ∞

Компьютеры весьма производительны…

…но их быстродействие не может быть бесконечно большим.

память > 0 ₽

Память дешевеет…

…но не может стать бесплатной.

Обоими ресурсами нужно распоряжаться разумно — и в этом помогают алгоритмы, эффективные в плане расходов времени и памяти.
Раздел 1.2 · Эффективность

Алгоритмы различаются сильнее, чем железо

Алгоритмы для одной и той же задачи часто различаются по эффективности намного значительнее, чем различия, вызванные разным аппаратным и программным обеспечением. Пример — две сортировки из главы 2.

Сортировка вставкой · insertion sort
c1 · n · n

Время ≈ c1n², пропорционально n². Типичная константа c1 меньше, чем у слияния: c1 < c2.

Сортировка слиянием · merge sort
c2 · n · lg n

Время ≈ c2n lg n, где lg n — краткая запись log2 n. Константа c2 больше — но сомножитель куда меньше.

n = 1 000 ≈ 2¹⁰
lg n ≈ 10
n = 1 000 000 ≈ 2²⁰
lg n ≈ 20
n = 1 000 000 000 ≈ 2³⁰
lg n ≈ 30
Сомножитель n вырос в миллион раз, а lg n прибавил всего 20.
Осторожно, ловушка обозначений: в книге lg n = log2 n, а не десятичный логарифм, как в школе. Поэтому lg 1000 ≈ 10 (2¹⁰ = 1024), а не 3.
Раздел 1.2 · Константы не спасают

Переломный момент наступит всегда

На малых n вставки обычно быстрее: константа меньше. Но с ростом n ничтожный lg n полностью компенсирует разницу констант. Не имеет значения, во сколько раз c1 меньше c2 — перелом всё равно наступит.

Во сколько раз c2 больше c1
×50
Слияние обгоняет вставки начиная с
n ≈ 439

Вставки: c1 · n², c1 = 1 Слияние: c2 · n · lg n
Раздел 1.2 · Эксперимент

Компьютер А против компьютера Б

Оба сортируют 10 миллионов чисел. Звучит внушительно, но это около 80 МБ восьмибайтовых целых — весьма немного даже для старых недорогих лэптопов.

Компьютер А
1010команд/с
10 миллиардов команд в секунду — быстрее любого последовательного компьютера на момент написания книги
Алгоритм
сортировка вставкой
Код
лучший в мире программист, машинный язык
Цена
2n² команд
vs
Компьютер Б
107команд/с
10 миллионов команд в секунду — в тысячу раз медленнее компьютера А
Алгоритм
сортировка слиянием
Код
программист-середнячок, язык высокого уровня, неэффективный компилятор
Цена
50 n lg n команд
Ваши ставки? У А железо в 1000 раз быстрее и константа в 25 раз меньше. У Б есть только алгоритм получше.
Раздел 1.2 · Результат

Медленный Б обгоняет в 17 раз

Компьютер А · вставки
2 · (107)2 команд1010 команд/с = 20 000 с
более 5,5 часа
Компьютер Б · слияние
50 · 107 · lg 107 команд107 команд/с ≈ 1163 с
менее 20 минут
А · вставки
—
Б · слияние
—
n = 10 млн
—
Раздел 1.2 · Алгоритмы и другие технологии

Алгоритмы — это технология

Пример с компьютерами А и Б показывает: алгоритмы, как и аппаратное обеспечение, следует рассматривать как технологию. Вложиться можно и в то, и в другое — и отдача сравнима.

Производительность
всей системы
=
Железо
у А — в 1000 раз быстрее
×
Алгоритм
у Б — n lg n вместо n²
«Общая производительность системы настолько же зависит от эффективности алгоритма, насколько и от мощности применяющегося аппаратного обеспечения. В области разработки алгоритмов происходит такое же быстрое развитие, как и в других компьютерных технологиях».
Раздел 1.2 · Алгоритмы и другие технологии

Нужны ли алгоритмы, если есть всё это?

Вопрос книги: так ли важны алгоритмы на современных компьютерах, если достигнуты выдающиеся успехи в других высоких технологиях? Нажмите на карточку — что у неё внутри.

Да, безусловно. Некоторым простым веб-приложениям алгоритмическое наполнение явно не нужно, но большинству — необходимо. А даже приложение без алгоритмов «на верхнем уровне» стоит на технологиях, внутри которых работают алгоритмы.
Раздел 1.2 · Пример из книги

Веб-служба «как добраться»

В основе — мощное железо, графический интерфейс, глобальная сеть и, возможно, ООП. Но саму задачу решают алгоритмы — нажмите на пункт:

Задача: найти самый быстрый путь от дома до клуба. Числа на дорогах — минуты в пути, в кружках — лучшее известное время до точки. Алгоритм Дейкстры, раздел 24.3.

  1. Берём ближайшую ещё не обработанную точку — время до неё уже окончательное.
  2. Смотрим её соседей: если через неё к соседу быстрее, записываем соседу новое время.
  3. Повторяем, пока не дойдём до клуба. Маршрут — цепочка «откуда пришли».
Нажмите «Найти маршрут» — шаги слева будут подсвечиваться по ходу работы.

Задача: дорога хранится как 300 точек. Когда карту отдаляют, мелкие изгибы становятся меньше пикселя — их не видно, но рисовать их всё равно пришлось бы. Какие точки можно выкинуть, не испортив форму?

Масштаб картыулица
  1. Соединяем концы участка прямой — синий пунктир; синяя полоса вокруг — допуск ε.
  2. Ищем точку, которая дальше всех от этой прямой, — оранжевая.
  3. Дальше допуска ε — оставляем её и повторяем для двух половинок. Ближе — выкидываем все точки между концами.

Задача: пользователь ищет «ул. Кормена, 31», но точных координат каждого дома в базе нет.

Номер дома31
  1. Что известно: отрезок улицы между двумя перекрёстками и номера домов на его концах — 1 и 99 (■ на карте).
  2. Какая доля пути:
  3. Где точка: — там и ставим метку ●.

Дома стоят неравномерно, поэтому метка может промахнуться на пару домов, — зато не нужно хранить координаты каждого дома. Это линейная интерполяция.

Не из книги · Примеряем на фронтенд

Алгоритмы, на которых стоит наш фронтенд

Упражнение 1.2.1 просит пример приложения, которому нужны алгоритмы. Далеко ходить не надо — они внутри инструментов, с которыми мы работаем каждый день.

React · reconciliation

Сравнение деревьев

Лучшие универсальные алгоритмы превращения одного дерева в другое работают за O(n³): 1000 элементов — порядка миллиарда сравнений. React берёт эвристику O(n): элементы разных типов дают разные деревья, а key подсказывает, какие дети стабильны.

O(n³) → O(n)
Vue 3 · keyed diff

Наибольшая возрастающая подпоследовательность

Когда список переставили, Vue ищет LIS среди старых позиций узлов: они остаются на месте, двигаются только остальные — минимум перемещений в DOM.

LIS · O(n log n)
React · Scheduler

Очередь задач — двоичная куча

Планировщик хранит задачи в min-heap, упорядоченной по сроку: самая срочная всегда наверху — O(1), добавить или снять задачу — O(log n). Кучи и очереди с приоритетами — глава 6.

min-heap · O(log n)
Git · diff

Алгоритм Майерса

По умолчанию git diff ищет кратчайший набор правок алгоритмом Майерса за O(ND), где D — число различий. Поэтому дифф почти одинаковых файлов строится мгновенно.

O(ND)
Бандлеры

Граф модулей

Сборщик строит граф импортов и обходит его от точки входа: что недостижимо, в бандл не попадёт. ES-модули и сами исполняются в порядке обхода графа в глубину. Графы — глава 22.

DFS · O(V + E)
Виртуальные списки

Бинарный поиск на каждый скролл

Чтобы показать 20 строк из 100 000, виртуальный список находит первую видимую строку по накопленным высотам бинарным поиском — ~17 шагов вместо перебора всех строк.

O(log n)
Раздел 1.2 · Итог

Чем больше задача, тем важнее алгоритм

Вычислительные возможности растут — и компьютеры берутся за всё более сложные задачи. А с ростом задачи различия в эффективности алгоритмов проявляются всё значительнее. Во сколько раз Б обгоняет А:

n = 1 млн
×2
200 с против 100 с
n = 10 млн
×17
5,6 ч против 19 мин
n = 100 млн
×150
23 дня против 3,7 ч
n = 1 млрд
×1 338
6,3 года против 1,7 дня

Полоски — в логарифмическом масштабе. Время — по формулам примера: 2n² / 10¹⁰ против 50 n lg n / 10⁷.

«Знание основных алгоритмов и методов их разработки — одна из характеристик, отличающих действительно умелого, опытного программиста от новичка. Располагая современными компьютерными технологиями, некоторые задачи можно решить и без основательного знания алгоритмов, однако знания в этой области позволяют достичь намного большего».
Раздел 1.2 · Упражнения

Разомнёмся: упражнения 1.2.1–1.2.3

1.2.1 · Обсуждение

Алгоритмы на уровне приложения

Приведите пример приложения, для которого необходимо алгоритмическое наполнение на уровне приложений, и обсудите функции этих алгоритмов.

Навигатор: кратчайший путь по графу дорог (Дейкстра, A*), геокодирование и интерполяция адресов, отрисовка карты. А ещё — всё с предыдущего слайда про фронтенд. Ваши примеры?
1.2.2 · Задача

8n² против 64 n lg n

На одной машине вставкам нужно 8n² шагов, слиянию — 64 n lg n. При каком n вставки станут медленнее слияния? lg — это log2, как во всей книге.

Делим на 8n: n < 8 log2 n.
1) Замена n = 2k: 2k < 8k. Это не степенное уравнение — k и в показателе, и снаружи, формулы нет. Зато степени двойки легко перебрать:
k=5: 32 < 40 ✓ · k=6: 64 > 48 ✗ → граница между 32 и 64.
2) Сужаем, как бинарным поиском:
n=43: 43 < 43,4 ✓ · n=44: 44 > 43,7 ✗
Вставки быстрее при 2 ≤ n ≤ 43, с n = 44 — слияние. Точный корень ≈ 43,56 (W-функция Ламберта, как в 1.2.3).
1.2.3 · Задача

100n² против 2n

При каком минимальном n алгоритм со временем 100n² работает быстрее, чем алгоритм со временем 2n, на одной и той же машине?

n = 15: 100 · 15² = 22 500 < 2¹⁵ = 32 768. При n = 14 ещё наоборот: 19 600 > 16 384. Экспонента обгоняет любой полином — вопрос лишь, когда. Разбор — на следующем слайде.
Упражнение 1.2.3 · Разбор

Полином против экспоненты

Полином
nk

Переменная — в основании, степень постоянна: n², n³, 100n² = 100 · n · n. С каждым шагом растёт всё медленнее: у n² при n = 15 шаг даёт всего ×1,14.

Экспонента
2n

Переменная — в показателе, основание постоянно: 2n, 3n. Каждый шаг удваивает значение — поэтому рано или поздно обгоняет любой полином.

100n² — полином 2n — экспонента
Алгебраическое решение
  1. 100n² < 2nобе части положительны — можно логарифмировать
  2. log2 100 + 2 log2 n < nlog2 возрастает, поэтому знак неравенства сохраняется
  3. 6,64 + 2 log2 n < nэкспонента «развернулась» в линейную n, полином — в логарифм
  4. правая часть: +1 за шаг, левая: +2 log2(1 + 1/n)2 log2(1 + 1/n) < 1 ⇔ (1 + 1/n)² < 2 ⇔ n > 2,41 — начав выполняться, неравенство уже не нарушится
  5. n = 14: 14,26 > 14 ✗ · n = 15: 14,46 < 15 ✓значит, наименьшее n = 15
А если полином огромной степени — n100?

При n = 100 он и правда больше: 100100 = 10200, а 2100 ≈ 1030. Но тот же приём с логарифмом даёт n < 100 log2 n — и экспонента обгоняет его с n = 997, дальше навсегда. Не путать со 100n: это не полином, а тоже экспонента, только с основанием 100.

Точный корень уравнения 100n² = 2n элементарной формулой не выражается — только через W-функцию Ламберта: n = −(2 / ln 2) · W−1(−ln 2 / 20) ≈ 14,32. Ближайшее целое сверху — 15.

Задача 1.1 · Сравнение времени работы

Какую задачу успеем решить за век?

Алгоритм выполняет f(n) операций. В условии задачи одна операция длится 1 мкс — компьютер делает 10⁶ операций в секунду, и все цифры верны только для этой скорости. Какое наибольшее n он успеет обработать? Нажмите на строку.

Скорость компьютера
f(n)СекундаМинутаЧасДеньМесяцГодВек

Месяц — 30 дней, год — 365 дней.

Что забрать с собой

Алгоритмы как технология — в пяти строках

Идеальному компьютеру алгоритмы нужны ради корректности, реальному — ещё и ради скорости.
Вывод 1
Время и память — ограниченные ресурсы, и расходует их прежде всего выбранный алгоритм.
Вывод 2
n² против n lg n: константы решают только на малых n — перелом наступает всегда.
Вывод 3
Железо в 1000 раз медленнее, но алгоритм лучше — и на 10 млн чисел это в 17 раз быстрее.
Вывод 4
Алгоритмы — такая же технология, как железо, GUI и сети. И они внутри каждой из них.
Вывод 5
Главная мысль
Производительность системы — это железо × алгоритм. Вкладываться в алгоритмы так же выгодно, как в железо, а их знание отличает опытного программиста от новичка.
Потяните за уголок карточки вправо

Что далее

Антон Помазков
Алгоритмы как технология Пройдено
Артём Никифоров