Обход в глубину, цвета вершин — различия между версиями
м (rollbackEdits.php mass rollback) |
|||
| (не показано 7 промежуточных версий 6 участников) | |||
| Строка 16: | Строка 16: | ||
В массиве <tex>\mathrm{visited[]}</tex> хранится информация о ''пройденных'' и ''не пройденных'' вершинах. | В массиве <tex>\mathrm{visited[]}</tex> хранится информация о ''пройденных'' и ''не пройденных'' вершинах. | ||
| − | '''function''' doDfs(G: '''Graph'''):<font color=darkgreen> // функция принимает граф G с количеством вершин n и выполняет обход в глубину во всем графе </font> | + | '''function''' doDfs(G[n]: '''Graph'''):<font color=darkgreen> // функция принимает граф G с количеством вершин n и выполняет обход в глубину во всем графе </font> |
| + | visited = array[n, ''false''] <font color=darkgreen> // создаём массив посещённых вершины длины n, заполненный ''false'' изначально</font> | ||
| + | |||
'''function''' dfs(u: '''int'''): | '''function''' dfs(u: '''int'''): | ||
visited[u] = ''true'' | visited[u] = ''true'' | ||
| Строка 23: | Строка 25: | ||
dfs(v) | dfs(v) | ||
| − | |||
'''for''' i = 1 '''to''' n | '''for''' i = 1 '''to''' n | ||
'''if''' '''not''' visited[i] | '''if''' '''not''' visited[i] | ||
| − | dfs(i) | + | dfs(i) |
=== Время работы === | === Время работы === | ||
| − | Оценим время работы обхода в глубину. Процедура <tex>\mathrm{dfs}</tex> вызывается от каждой вершины не более одного раза, а внутри процедуры рассматриваются все такие [[Основные определения теории графов|ребра]] <tex>\{e\ |\ begin(e) = u\}</tex>. Всего таких ребер для всех вершин в графе <tex>O(E)</tex>, следовательно, время работы алгоритма оценивается как <tex>O(V+E)</tex>. | + | Оценим время работы обхода в глубину. Процедура <tex>\mathrm{dfs}</tex> вызывается от каждой вершины не более одного раза, а внутри процедуры рассматриваются все такие [[Основные определения теории графов|ребра]] <tex>\{e\ |\ \mathrm{begin(e)} = u\}</tex>. Всего таких ребер для всех вершин в графе <tex>O(E)</tex>, следовательно, время работы алгоритма оценивается как <tex>O(V+E)</tex>. |
== Цвета вершин == | == Цвета вершин == | ||
| Строка 45: | Строка 46: | ||
Отличие реализации с цветами от предыдущей лишь в массиве <tex>\mathrm{visited[]}</tex>, который мы назовем теперь <tex>\mathrm{color[]}</tex>. В нем будет хранится информация о цветах вершин. | Отличие реализации с цветами от предыдущей лишь в массиве <tex>\mathrm{visited[]}</tex>, который мы назовем теперь <tex>\mathrm{color[]}</tex>. В нем будет хранится информация о цветах вершин. | ||
| − | '''function''' doDfs(G: '''Graph'''):<font color=darkgreen> // функция принимает граф G с количеством вершин n и выполняет обход в глубину во всем графе </font> | + | '''function''' doDfs(G[n]: '''Graph'''):<font color=darkgreen> // функция принимает граф G с количеством вершин n и выполняет обход в глубину во всем графе </font> |
| + | color = array[n, ''white''] | ||
| + | |||
'''function''' dfs(u: '''int'''): | '''function''' dfs(u: '''int'''): | ||
color[u] = ''gray'' | color[u] = ''gray'' | ||
| Строка 53: | Строка 56: | ||
color[u] = ''black'' | color[u] = ''black'' | ||
| − | |||
'''for''' i = 1 '''to''' n | '''for''' i = 1 '''to''' n | ||
'''if''' color[i] == ''white'' | '''if''' color[i] == ''white'' | ||
dfs(i) | dfs(i) | ||
| − | + | ||
=== Пример === | === Пример === | ||
Рассмотрим, как будут изменяться цвета вершин при обходе в глубину данного графа. | Рассмотрим, как будут изменяться цвета вершин при обходе в глубину данного графа. | ||
Текущая версия на 19:38, 4 сентября 2022
Обход в глубину (поиск в глубину, англ. Depth-First Search, DFS) — один из основных методов обхода графа, часто используемый для проверки связности, поиска цикла и компонент сильной связности и для топологической сортировки.
Содержание
Алгоритм
Общая идея
Общая идея алгоритма состоит в следующем: для каждой не пройденной вершины необходимо найти все не пройденные смежные вершины и повторить поиск для них.
Пошаговое представление
- Выбираем любую вершину из еще не пройденных, обозначим ее как .
- Запускаем процедуру
- Помечаем вершину как пройденную
- Для каждой не пройденной смежной с вершиной (назовем ее ) запускаем
- Повторяем шаги 1 и 2, пока все вершины не окажутся пройденными.
Реализация
В массиве хранится информация о пройденных и не пройденных вершинах.
function doDfs(G[n]: Graph): // функция принимает граф G с количеством вершин n и выполняет обход в глубину во всем графе
visited = array[n, false] // создаём массив посещённых вершины длины n, заполненный false изначально
function dfs(u: int):
visited[u] = true
for v: (u, v) in G
if not visited[v]
dfs(v)
for i = 1 to n
if not visited[i]
dfs(i)
Время работы
Оценим время работы обхода в глубину. Процедура вызывается от каждой вершины не более одного раза, а внутри процедуры рассматриваются все такие ребра . Всего таких ребер для всех вершин в графе , следовательно, время работы алгоритма оценивается как .
Цвета вершин
Зачастую, простой информации "были/не были в вершине" не хватает для конкретных целей.
Поэтому в процессе алгоритма вершинам задают некоторые цвета:
- если вершина белая, значит, мы в ней еще не были, вершина не пройдена;
- серая — вершина проходится в текущей процедуре ;
- черная — вершина пройдена, все итерации от нее завершены.
Такие "метки" в основном используются при поиске цикла.
Реализация
Отличие реализации с цветами от предыдущей лишь в массиве , который мы назовем теперь . В нем будет хранится информация о цветах вершин.
function doDfs(G[n]: Graph): // функция принимает граф G с количеством вершин n и выполняет обход в глубину во всем графе
color = array[n, white]
function dfs(u: int):
color[u] = gray
for v: (u, v) in G
if color[v] == white
dfs(v)
color[u] = black
for i = 1 to n
if color[i] == white
dfs(i)
Пример
Рассмотрим, как будут изменяться цвета вершин при обходе в глубину данного графа.
Дерево обхода в глубину
Рассмотрим подграф предшествования обхода в глубину , где , где в свою очередь — вершина, от которой был вызван (для вершин, от которых был вызван нерекурсивно это значение соответственно равно ). Подграф предшествования поиска в глубину образует лес обхода в глубину, который состоит из нескольких деревьев обхода в глубину. С помощью полученного леса можно классифицировать ребра графа :
- Ребрами дерева назовем те ребра из , которые вошли в .
- Ребра , соединяющие вершину с её предком в дереве обхода в глубину назовем обратными ребрами (для неориентированного графа предок должен быть не родителем, так как иначе ребро будет являться ребром дерева).
- Ребра , не являющиеся ребрами дерева и соединяющие вершину с её потомком в дереве обхода в глубину назовем прямыми ребрами (в неориентированном графе нет разницы между прямыми и обратными ребрами, поэтому все такие ребра считаются обратными).
- Все остальные ребра назовем перекрестными ребрами — такие ребра могут соединять вершины одного и того же дерева обхода в глубину, когда ни одна из вершин не является предком другой, или соединять вершины в разных деревьях.
Алгоритм можно модифицировать так, что он будет классифицировать встречающиеся при работе ребра. Ключевая идея состоит в том, что каждое ребро можно классифицировать при помощи цвета вершины при первом его исследовании, а именно:
- Белый цвет вершины по определению говорит о том, что это ребро дерева.
- Серый цвет в силу того, что серые вершины всегда образуют нисходящий путь в каком-либо из деревьев и встреченная вершина лежит на нем выше вершины , определяет обратное ребро (для неориентированного графа необходимо проверить условие ).
- Черный цвет, соответственно, указывает на прямое или перекрестное ребро.
См. также
Источники информации
- Википедия — Поиск в глубину
- Wikipedia — Depth-first search
- Обход в глубину. Реализации.
- Томас Кормен, Чарльз Лейзерсон, Рональд Ривест, Клиффорд Штайн. Алгоритмы: построение и анализ, второе издание. Пер. с англ. — Издательский дом "Вильямс", 2007. — 1296 с. — Глава 22. Элементарные алгоритмы для работы с графами.







