Алгоритмы

Топологическая сортировка: Порядок зависимостей

Цели урока

  • Понять задачу топологической сортировки
  • Реализовать через DFS
  • Реализовать алгоритм Кана (BFS)
  • Детектировать циклы

Предварительные знания

  • DFS
  • DFS: Поиск в глубину

Каждый раз, когда вы запускаете npm install или make, за кулисами работает топологическая сортировка. Она гарантирует, что зависимости собираются в правильном порядке.

  • Системы сборки (Make, Gradle, Bazel)
  • Пакетные менеджеры (npm, pip, cargo)
  • Компиляторы (порядок компиляции модулей)
  • Spreadsheets (порядок пересчёта формул)

Алгоритм Кана 1962 года и метод через DFS

Топологическая сортировка как явный алгоритм появилась в 1962 году в короткой заметке Артура Кана Topological Sorting of Large Networks в Communications of the ACM. Кан работал с сетевыми моделями проектов вроде PERT, где задачи зависят друг от друга, и нужно выстроить их в выполнимый порядок. Его метод прост и нагляден: находим вершины без входящих рёбер (источники), убираем их, обновляем степени соседей, повторяем. Если в какой-то момент источников нет, а вершины ещё остались, в графе есть цикл, и порядка не существует. Второй способ, через обход в глубину, стал общеизвестен после того, как Роберт Тарьян формализовал DFS-технику в 1970-х: достаточно взять вершины в обратном порядке завершения DFS. Оба работают за O(V + E). Сама идея старше: она неявно присутствовала в анализе сетей PERT и CPM конца 1950-х, разработанном для управления крупными инженерными и военными проектами.

Идея: упорядочить зависимости

**Задача:** даны зависимости между задачами. Нужно найти порядок выполнения, при котором каждая задача выполняется после всех своих зависимостей.

**Требования:**

  • Граф должен быть **ориентированным** (DAG = Directed Acyclic Graph)
  • **Нет циклов!** (иначе порядок невозможен)
  • Если есть ребро u → v, то u должно быть ПЕРЕД v

**Цикл = нет решения.** A зависит от B, B от C, C от A - ни один нельзя выполнить первым!

Граф: A→B, B→C, C→A. Топологическая сортировка:

Алгоритм через DFS

**Идея:** при DFS вершина «закрывается» после всех её потомков. Значит, обратный порядок закрытия - топологический!

Почему результат DFS нужно развернуть (reverse)?

Алгоритм Кана (BFS)

**Альтернатива:** алгоритм Кана. Итеративно убираем вершины без входящих рёбер.

DFSKahn
ПодходОбратный порядок выходаУдаление источников
Детекция циклаGRAY→GRAY реброlen(result) < V
ПамятьO(V) рекурсияO(V) очередь
ПараллелизацияСложноПроще (независимые источники)

Kahn обнаруживает цикл когда:

Применения

**1. Системы сборки (Make, Gradle, npm):**

**2. Планирование задач:**

**3. Компиляторы (порядок инициализации):**

**4. Spreadsheets (пересчёт формул):**

В npm/yarn зависимости образуют цикл. Что произойдёт?

Топологическая сортировка

  • Линейный порядок вершин DAG
  • DFS: обратный порядок выхода
  • Kahn: итеративно убираем источники
  • Цикл = невозможно (DFS: GRAY→GRAY, Kahn: result < V)
  • O(V + E) время для обоих алгоритмов

Связанные темы

Топологическая сортировка связана с анализом графов.

  • DFS — Основа алгоритма
  • SCC — Сильно связные компоненты
  • Критический путь — Самый длинный путь в DAG

Связанные уроки

  • alg-13-dfs — Порядок выхода DFS даёт топологический порядок
  • ds-16-graphs-intro — Топосортировка работает на направленных ациклических графах
  • sd-10-microservices — Порядок сборки зависимостей сервисов - это топосортировка
  • prog-09-recursion — Вариант через DFS естественно рекурсивен
  • comp-22-ssa
  • plt-27-ir-optimization
Топологическая сортировка: Порядок зависимостей

0

1

Войти