Объясните понятие Big O и различие между временной и пространственной сложностью на примере алгоритма поиска в глубину (DFS) и поиска в ширину (BFS) графа.
Big O — асимптотическая верхняя оценка роста ресурса (времени или памяти) по мере роста размера входа. Формально выражает, как меняется количество операций или дополнительной памяти при n→∞n \to \inftyn→∞; константы и низкоуровневые детали игнорируются. Временная сложность — сколько простейших операций (например, проверок/просмотров рёбер/вершин) выполняет алгоритм в зависимости от размера входа. Пространственная сложность — сколько дополнительной памяти (не считая памяти, требуемой для хранения входных данных) нужно алгоритму. Применение к DFS и BFS (граф представлен списками смежности, число вершин ∣V∣|V|∣V∣, число рёбер ∣E∣|E|∣E∣): - Время: - DFS (рекурсивный или стековый): посещает каждую вершину и каждое ребро не более одного раза, поэтому временная сложность O(∣V∣+∣E∣)\;O(|V|+|E|)O(∣V∣+∣E∣). - BFS: аналогично посещает каждую вершину и ребро максимум один раз, временная сложность O(∣V∣+∣E∣)\;O(|V|+|E|)O(∣V∣+∣E∣). - При представлении графа матрицей смежности обеим алгоритмам время будет O(∣V∣2)\;O(|V|^2)O(∣V∣2), т.к. приходится сканировать строки матрицы. - Память (дополнительная): - DFS: - Рекурсивная реализация: стек вызовов глубиной в худшем случае ∣V∣|V|∣V∣, т.е. O(∣V∣)\;O(|V|)O(∣V∣). - Итеративная (явный стек): аналогично O(∣V∣)\;O(|V|)O(∣V∣). - В частных случаях на сбалансированном дереве глубина меньше: для дерева с nnn вершинами и высотой hhh — стек O(h)\;O(h)O(h); для сбалансированного бинарного дерева h=O(logn)h = O(\log n)h=O(logn). - BFS: - Использует очередь для фронта обхода; в худшем случае может одновременно содержать Θ(∣V∣)\Theta(|V|)Θ(∣V∣) вершин, т.е. пространство O(∣V∣)\;O(|V|)O(∣V∣). - В частном примере полного бинарного дерева с nnn вершинами максимальный уровень содержит Θ(n)\Theta(n)Θ(n) вершин → очередь O(n)\;O(n)O(n). Короткое сравнение/вывод: - По времени для стандартных представлений оба алгоритма одинаковы: O(∣V∣+∣E∣)\;O(|V|+|E|)O(∣V∣+∣E∣) (или O(∣V∣2)\;O(|V|^2)O(∣V∣2) для матрицы). - По памяти различия зависят от структуры графа: в худшем случае оба требуют O(∣V∣)\;O(|V|)O(∣V∣), но на «глубоких» и сбалансированных деревьях DFS может требовать лишь O(logn)\;O(\log n)O(logn) (рекурсивная глубина), тогда как BFS может требовать O(n)\;O(n)O(n) для хранения уровня.
Временная сложность — сколько простейших операций (например, проверок/просмотров рёбер/вершин) выполняет алгоритм в зависимости от размера входа.
Пространственная сложность — сколько дополнительной памяти (не считая памяти, требуемой для хранения входных данных) нужно алгоритму.
Применение к DFS и BFS (граф представлен списками смежности, число вершин ∣V∣|V|∣V∣, число рёбер ∣E∣|E|∣E∣):
- Время:
- DFS (рекурсивный или стековый): посещает каждую вершину и каждое ребро не более одного раза, поэтому временная сложность O(∣V∣+∣E∣)\;O(|V|+|E|)O(∣V∣+∣E∣).
- BFS: аналогично посещает каждую вершину и ребро максимум один раз, временная сложность O(∣V∣+∣E∣)\;O(|V|+|E|)O(∣V∣+∣E∣).
- При представлении графа матрицей смежности обеим алгоритмам время будет O(∣V∣2)\;O(|V|^2)O(∣V∣2), т.к. приходится сканировать строки матрицы.
- Память (дополнительная):
- DFS:
- Рекурсивная реализация: стек вызовов глубиной в худшем случае ∣V∣|V|∣V∣, т.е. O(∣V∣)\;O(|V|)O(∣V∣).
- Итеративная (явный стек): аналогично O(∣V∣)\;O(|V|)O(∣V∣).
- В частных случаях на сбалансированном дереве глубина меньше: для дерева с nnn вершинами и высотой hhh — стек O(h)\;O(h)O(h); для сбалансированного бинарного дерева h=O(logn)h = O(\log n)h=O(logn).
- BFS:
- Использует очередь для фронта обхода; в худшем случае может одновременно содержать Θ(∣V∣)\Theta(|V|)Θ(∣V∣) вершин, т.е. пространство O(∣V∣)\;O(|V|)O(∣V∣).
- В частном примере полного бинарного дерева с nnn вершинами максимальный уровень содержит Θ(n)\Theta(n)Θ(n) вершин → очередь O(n)\;O(n)O(n).
Короткое сравнение/вывод:
- По времени для стандартных представлений оба алгоритма одинаковы: O(∣V∣+∣E∣)\;O(|V|+|E|)O(∣V∣+∣E∣) (или O(∣V∣2)\;O(|V|^2)O(∣V∣2) для матрицы).
- По памяти различия зависят от структуры графа: в худшем случае оба требуют O(∣V∣)\;O(|V|)O(∣V∣), но на «глубоких» и сбалансированных деревьях DFS может требовать лишь O(logn)\;O(\log n)O(logn) (рекурсивная глубина), тогда как BFS может требовать O(n)\;O(n)O(n) для хранения уровня.