Обход в ширину — различия между версиями
(→Корректность) |
AKhimulya (обсуждение | вклад) (оформление англоязычных терминов, псевдокода и источников информации) |
||
Строка 1: | Строка 1: | ||
− | '''Обход в ширину''' ( | + | '''Обход в ширину''' (Поиск в ширину, англ. ''BFS'', ''Breadth-first search'') — один из простейших алгоритмов обхода графа, являющийся основой для многих важных алгоритмов для работы с графами. |
== Алгоритм == | == Алгоритм == | ||
Строка 43: | Строка 43: | ||
=== Реализация === | === Реализация === | ||
− | + | Предложенная ниже функция возвращает расстояние между вершинами <tex> source </tex> и <tex> target </target>. <tex>E</tex> - список ребер, Q - очередь. Множество <tex> X </tex> не хранится, вместо него используются расстояния в дереве обхода в ширину. ЗаметимЮ что расстояние от вершины <tex>source</tex> до вершины <tex>u</tex>, хранится в поле <tex>d[u]</tex>. | |
− | '''BFS'''(< | + | '''int''' '''BFS'''(E: '''list'''<'''int''', '''int'''>, source: '''int''', destination: '''int''') |
− | + | d.fill(<tex> \infty </tex>) | |
− | + | d[source] = 0 | |
− | + | Q = <tex> \varnothing </tex> | |
− | + | Q.push(source) | |
− | + | '''while''' Q <tex> \ne \varnothing </tex> | |
− | + | q = Q.pop() | |
− | + | '''for''' <q, v> '''in''' E | |
− | + | '''if''' v == <tex> \infty </tex> | |
− | + | d[v] = d[q] + 1 | |
+ | Q.push(v) | ||
+ | '''return''' d[destination] | ||
− | == | + | == Источники информации == |
+ | * Томас Х. Кормен, Чарльз И. Лейзерсон, Рональд Л. Ривест, Клиффорд Штайн Алгоритмы: построение и анализ — 2-е изд. — М.: «Вильямс», 2007. — с. 459. — ISBN 5-8489-0857-4 | ||
* [http://e-maxx.ru/algo/bfs Поиск в ширину на e-maxx.ru] | * [http://e-maxx.ru/algo/bfs Поиск в ширину на e-maxx.ru] | ||
− | * [ | + | * [[wikipedia:en:Breadth-first_search| Wikipedia {{---}} Breadth-first search]] |
+ | * [[wikipedia:ru:Поиск_в_ширину| Wikipedia {{---}} Поиск в ширину]] | ||
* [http://rain.ifmo.ru/cat/view.php/vis/graph-general/bfs-2002 Визуализатор алгоритма] | * [http://rain.ifmo.ru/cat/view.php/vis/graph-general/bfs-2002 Визуализатор алгоритма] | ||
− | |||
− | |||
− | |||
− | |||
[[Категория: Алгоритмы и структуры данных]] | [[Категория: Алгоритмы и структуры данных]] | ||
[[Категория: Кратчайшие пути в графах]] | [[Категория: Кратчайшие пути в графах]] |
Версия 20:17, 2 декабря 2014
Обход в ширину (Поиск в ширину, англ. BFS, Breadth-first search) — один из простейших алгоритмов обхода графа, являющийся основой для многих важных алгоритмов для работы с графами.
Содержание
Алгоритм
Общая идея
Пусть задан невзвешенный граф
, в котором выделена исходная вершина . Для алгоритма нам потребуются очередь, которая сначала содержит только , и множество посещенных вершин , которое изначально тоже содержит только . На каждом шаге алгоритм вынимает из начала очереди вершину, рассматривает все исходящие из нее ребра и добавляет все связанные с ней непосещенные вершины в и в конец очереди. Если очередь пуста, то алгоритм завершает работу.Поиск в ширину также может построить дерево поиска в ширину. Изначально оно состоит из одного корня
. Когда мы добавляем непосещенную вершину в очередь, то добавляем ее и ребро, по которому мы до нее дошли, в дерево. Поскольку каждая вершина может быть посещена не более одного раза, она имеет не более одного родителя. После окончания работы алгоритма для каждой достижимой из вершины путь в дереве поиска в ширину соответствует кратчайшему пути от до в .Также можно для каждой вершины
считать длину этого пути, равную . Можно считать, что для непосещенных вершин эта длина бесконечно велика. Тогда на каждом шаге длина пути до равна , если посещена и в противном случае. Отсюда следует, что если на каждом шаге обновлять длины путей, то информация о множестве является избыточной, и его можно не хранить.Анализ времени работы
Оценим время работы для входного графа
. В очередь добавляются только непосещенные вершины, поэтому каждая вершина посещается не более одного раза. Операции внесения в очередь и удаления из нее требуют времени, так что общее время работы с очередью составляет операций. Для каждой вершины рассматривается не более ребер, инцидентных ей. Так как , то время, используемое на работу с ребрами, составляет . Поэтому общее время работы алгоритма поиска в ширину — .Корректность
Утверждение: |
В очереди поиска в ширину расстояние вершин до монотонно неубывает. |
Докажем это утверждение индукцией по числу выполненных алгоритмом шагов. База: изначально очередь содержит только одну вершину Переход: пусть после с расстоянием 0, утверждение верно. -ого шага алгоритма очередь содержит вершин с расстоянием и вершин с расстоянием . Тогда на -ом шаге мы извлечем из очереди одну вершину и добавим в нее все непосещенные( вершин), связанные с ней; расстояние до них, очевидно, будет равно . У нас останется (возможно, 0) вершин с расстоянием и вершин с расстоянием k + 1, что соответствует нашему инварианту. |
Теорема: |
Алгоритм поиска в ширину в невзвешенном графе находит длины кратчайших путей до всех достижимых вершин. |
Доказательство: |
Допустим, что это не так. Выберем из вершин, для которых кратчайшие пути от найдены некорректно, ту, настоящее расстояние до которой минимально. Пусть это вершина , и она имеет своим предком в дереве обхода в ширину , а предок в кратчайшем пути до — вершина .Так как — предок в кратчайшем пути, то , и расстояние до w найдено верно, . Значит, .Так как Расстояние до — предок в дереве обхода в ширину, то . найдено некорректно, поэтому . Подставляя сюда два последних равенства, получаем , то есть, . Из ранее доказанной леммы следует, что в этом случае вершина попала в очередь и была обработана раньше, чем . Но она соединена с , значит, не может быть предком в дереве обхода в ширину, мы пришли к противоречию, следовательно, найденные расстояния до всех вершин являются кратчайшими. |
Реализация
Предложенная ниже функция возвращает расстояние между вершинами
и - список ребер, Q - очередь. Множество не хранится, вместо него используются расстояния в дереве обхода в ширину. ЗаметимЮ что расстояние от вершины до вершины , хранится в поле .int BFS(E: list<int, int>, source: int, destination: int) d.fill() d[source] = 0 Q = Q.push(source) while Q q = Q.pop() for <q, v> in E if v == d[v] = d[q] + 1 Q.push(v) return d[destination]
Источники информации
- Томас Х. Кормен, Чарльз И. Лейзерсон, Рональд Л. Ривест, Клиффорд Штайн Алгоритмы: построение и анализ — 2-е изд. — М.: «Вильямс», 2007. — с. 459. — ISBN 5-8489-0857-4
- Поиск в ширину на e-maxx.ru
- Wikipedia — Breadth-first search
- Wikipedia — Поиск в ширину
- Визуализатор алгоритма