Обход в ширину — различия между версиями
Sementry (обсуждение | вклад) (почти полностью переписал статью) |
|||
Строка 1: | Строка 1: | ||
{{В разработке}} | {{В разработке}} | ||
− | '''Обход в ширину''' ('''Поиск в ширину, BFS''', Breadth-first search) — один из простейших алгоритмов обхода графа, являющийся основой для многих важных алгоритмов для работы с графами | + | '''Обход в ширину''' ('''Поиск в ширину, BFS''', Breadth-first search) — один из простейших алгоритмов обхода графа, являющийся основой для многих важных алгоритмов для работы с графами. |
− | ==Алгоритм== | + | == Алгоритм == |
− | ===Общая идея=== | + | === Общая идея === |
− | |||
− | + | Пусть задан невзвешенный граф <tex>G = (V, E)</tex>, в котором выделена исходная вершина <tex>s</tex>. Для алгоритма нам потребуются очередь, которая сначала содержит только <tex> s </tex>, и множество посещенных вершин <tex> X </tex>, которое изначально тоже содержит только <tex> s </tex>. На каждом шаге алгоритм вынимает из начала очереди вершину, рассматривает все исходящие из нее ребра и добавляет все связанные с ней непосещенные вершины в <tex> X </tex> и в конец очереди. Если очередь пуста, то алгоритм завершает работу. | |
− | Поиск в ширину | + | Поиск в ширину также может построить дерево поиска в ширину. Изначально оно состоит из одного корня <tex> s </tex>. Когда мы добавляем непосещенную вершину в очередь, то добавляем ее и ребро, по которому мы до нее дошли, в дерево. Поскольку каждая вершина может быть посещена не более одного раза, она имеет не более одного родителя. После окончания работы алгоритма для каждой достижимой из <tex> s </tex> вершины <tex> t </tex> путь в дереве поиска в ширину соответствует кратчайшему пути от <tex> s </tex> до <tex> t </tex> в <tex> G </tex>. |
+ | |||
+ | Также можно для каждой вершины <tex> t \in V </tex> считать длину этого пути, равную <tex> d[t] </tex>. Можно считать, что для непосещенных вершин эта длина бесконечно велика. Тогда на каждом шаге длина пути до <tex> t </tex> равна <tex> \rho(s, t) </tex>, если <tex> t </tex> посещена и <tex> \infty </tex> в противном случае. Отсюда следует, что если на каждом шаге обновлять длины путей, то информация о множестве <tex> X </tex> является избыточной, и его можно не хранить. | ||
+ | |||
+ | == Анализ времени работы == | ||
+ | |||
+ | Оценим время работы для входного графа <tex>G = (V, E)</tex>. В очередь добавляются только непосещенные вершины, поэтому каждая вершина посещается не более одного раза. Операции внесения в очередь и удаления из нее требуют <tex> O(1) </tex> времени, так что общее время работы с очередью составляет <tex> O(V) </tex> операций. Для каждой вершины <tex> v </tex> рассматривается не более <tex> deg\ v </tex> ребер, инцидентных ей. Так как <tex> \sum_{v \in V} deп\ v = 2|E| </tex>, то время, используемое на работу с ребрами, составляет <tex> O(E) </tex>. Поэтому общее время работы алгоритма поиска в ширину — <tex> O(V + E) </tex>. | ||
+ | |||
+ | === Корректность === | ||
+ | |||
+ | {{Утверждение | ||
+ | |statement= | ||
+ | В алгоритме поиска в ширину очередь всегда содержит сначала вершины с расстоянием k, а потом, возможно, вершины с расстоянием k + 1. | ||
+ | |proof= | ||
+ | Докажем это утверждение индукцией по шагам алгоритма. | ||
+ | |||
+ | База: изначально очередь содержит только одну вершину <tex> s </tex> с расстоянием 0, утверждение верно. | ||
+ | |||
+ | Переход: пусть после <tex> l </tex>-ого шага алгоритма очередь содержит <tex> p </tex> вершин с расстоянием <tex> k </tex> и <tex> q </tex> вершин с расстоянием <tex> k + 1 </tex>. Тогда на <tex> l+1 </tex>-ом шаге мы извлечем из очереди одну вершину и добавим в нее все непосещенные(<tex> r </tex> вершин), связанные с ней; расстояние до них, очевидно, будет равно <tex> k + 1 </tex>. У нас останется <tex> p - 1 </tex>(возможно, 0) вершин с расстоянием <tex> k </tex> и <tex> q + r </tex> вершин с расстоянием k + 1, что соответствует нашему инварианту. | ||
+ | }} | ||
+ | |||
+ | {{Теорема | ||
+ | |statement= | ||
+ | Алгоритм поиска в ширину в невзвешенном графе находит оптимальные расстояния до всех достижимых вершин. | ||
+ | |proof= | ||
+ | Допустим, что это не так. Выберем из вершин, для которых найдено неоптимальное расстояние от <tex> s </tex> ту, которая находится на минимальном расстоянии. Пусть это вершина <tex> u </tex>, и она имеет своим предком в дереве обхода в ширину <tex> v </tex>, а предкок в оптимальном пути до <tex> v </tex> — вершина <tex> w </tex>. Расстояние до вершин <tex> v <tex> и <tex> w </tex> найдено корректно, путь через <tex> w </tex> оптимальный, а через <tex> v </tex> — нет, поэтому <tex> d[w] < d[v] </tex>. Из ранее доказанной леммы следует, что в этом случае вершина <tex> w </tex> попала в очередь и была обработана раньше, чем <tex> v </tex>. Но она соединена с <tex> u </tex>, значит, <tex> v </tex> не может быть предком <tex> u </tex> в дереве обхода в ширину, мы пришли к противоречию, и найденные расстояния до всех вершин оптимальны. | ||
+ | }} | ||
+ | |||
+ | === Реализация === | ||
+ | |||
+ | В приведенном ниже псевдокоде <tex> G = (V, E) </tex> - входной граф, <tex> s </tex> - выделенная вершина, Q - очередь. Множество <tex> X </tex> не хранится, вместо него использются расстояния в дереве обхода в ширину; расстояние от <tex>s</tex> до вершины <tex>u</tex>, вычисляемое алгоритмом, хранится в поле <tex>d[u]</tex>. | ||
− | |||
− | |||
'''BFS'''(<tex>G</tex>, <tex>s</tex>) | '''BFS'''(<tex>G</tex>, <tex>s</tex>) | ||
− | + | 1 d[s] <tex> \leftarrow </tex> 0 | |
− | + | 2 Q <tex> \leftarrow \varnothing </tex> | |
− | + | 3 Q.push(s) | |
− | + | 4 '''while''' Q <tex> \ne \varnothing </tex> | |
− | + | 5 '''do''' u <tex> \leftarrow </tex> Q.pop | |
− | + | 6 '''for''' v: uv <tex> \in </tex> E | |
− | + | 7 '''do''' '''if''' d[v] = <tex> \infty </tex> | |
− | + | 8 '''then''' d[v] <tex> \leftarrow </tex> d[u] + 1 | |
− | + | 9 Q.push(v) | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | == | + | == Литература == |
− | |||
− | |||
*Томас Х. Кормен и др. Алгоритмы: построение и анализ = INTRODUCTION TO ALGORITHMS. — 2-е изд. — М.: «Вильямс», 2006. — С. 1296. — ISBN 0-07-013151-1 | *Томас Х. Кормен и др. Алгоритмы: построение и анализ = INTRODUCTION TO ALGORITHMS. — 2-е изд. — М.: «Вильямс», 2006. — С. 1296. — ISBN 0-07-013151-1 | ||
+ | |||
+ | == Ссылки == | ||
+ | |||
+ | [http://e-maxx.ru/algo/bfs Поиск в ширину на e-maxx.ru] | ||
+ | [http://ru.wikipedia.org/wiki/Поиск_в_ширину Поиск в ширину в Википедии] | ||
+ | [http://rain.ifmo.ru/cat/view.php/vis/graph-general/bfs-2002 Визуализатор алгоритма] | ||
+ | |||
[[Категория: Алгоритмы и структуры данных]] | [[Категория: Алгоритмы и структуры данных]] | ||
[[Категория: Кратчайшие пути в графах]] | [[Категория: Кратчайшие пути в графах]] |
Версия 04:40, 27 октября 2011
Эта статья находится в разработке!
Обход в ширину (Поиск в ширину, BFS, Breadth-first search) — один из простейших алгоритмов обхода графа, являющийся основой для многих важных алгоритмов для работы с графами.
Содержание
Алгоритм
Общая идея
Пусть задан невзвешенный граф
, в котором выделена исходная вершина . Для алгоритма нам потребуются очередь, которая сначала содержит только , и множество посещенных вершин , которое изначально тоже содержит только . На каждом шаге алгоритм вынимает из начала очереди вершину, рассматривает все исходящие из нее ребра и добавляет все связанные с ней непосещенные вершины в и в конец очереди. Если очередь пуста, то алгоритм завершает работу.Поиск в ширину также может построить дерево поиска в ширину. Изначально оно состоит из одного корня
. Когда мы добавляем непосещенную вершину в очередь, то добавляем ее и ребро, по которому мы до нее дошли, в дерево. Поскольку каждая вершина может быть посещена не более одного раза, она имеет не более одного родителя. После окончания работы алгоритма для каждой достижимой из вершины путь в дереве поиска в ширину соответствует кратчайшему пути от до в .Также можно для каждой вершины
считать длину этого пути, равную . Можно считать, что для непосещенных вершин эта длина бесконечно велика. Тогда на каждом шаге длина пути до равна , если посещена и в противном случае. Отсюда следует, что если на каждом шаге обновлять длины путей, то информация о множестве является избыточной, и его можно не хранить.Анализ времени работы
Оценим время работы для входного графа
. В очередь добавляются только непосещенные вершины, поэтому каждая вершина посещается не более одного раза. Операции внесения в очередь и удаления из нее требуют времени, так что общее время работы с очередью составляет операций. Для каждой вершины рассматривается не более ребер, инцидентных ей. Так как , то время, используемое на работу с ребрами, составляет . Поэтому общее время работы алгоритма поиска в ширину — .Корректность
Утверждение: |
В алгоритме поиска в ширину очередь всегда содержит сначала вершины с расстоянием k, а потом, возможно, вершины с расстоянием k + 1. |
Докажем это утверждение индукцией по шагам алгоритма. База: изначально очередь содержит только одну вершину Переход: пусть после с расстоянием 0, утверждение верно. -ого шага алгоритма очередь содержит вершин с расстоянием и вершин с расстоянием . Тогда на -ом шаге мы извлечем из очереди одну вершину и добавим в нее все непосещенные( вершин), связанные с ней; расстояние до них, очевидно, будет равно . У нас останется (возможно, 0) вершин с расстоянием и вершин с расстоянием k + 1, что соответствует нашему инварианту. |
Теорема: |
Алгоритм поиска в ширину в невзвешенном графе находит оптимальные расстояния до всех достижимых вершин. |
Доказательство: |
Допустим, что это не так. Выберем из вершин, для которых найдено неоптимальное расстояние от | ту, которая находится на минимальном расстоянии. Пусть это вершина , и она имеет своим предком в дереве обхода в ширину , а предкок в оптимальном пути до — вершина . Расстояние до вершин найдено корректно, путь через оптимальный, а через — нет, поэтому . Из ранее доказанной леммы следует, что в этом случае вершина попала в очередь и была обработана раньше, чем . Но она соединена с , значит, не может быть предком в дереве обхода в ширину, мы пришли к противоречию, и найденные расстояния до всех вершин оптимальны.
Реализация
В приведенном ниже псевдокоде
- входной граф, - выделенная вершина, Q - очередь. Множество не хранится, вместо него использются расстояния в дереве обхода в ширину; расстояние от до вершины , вычисляемое алгоритмом, хранится в поле .BFS(, ) 1 d[s] 0 2 Q 3 Q.push(s) 4 while Q 5 do u Q.pop 6 for v: uv E 7 do if d[v] = 8 then d[v] d[u] + 1 9 Q.push(v)
Литература
- Томас Х. Кормен и др. Алгоритмы: построение и анализ = INTRODUCTION TO ALGORITHMS. — 2-е изд. — М.: «Вильямс», 2006. — С. 1296. — ISBN 0-07-013151-1
Ссылки
Поиск в ширину на e-maxx.ru Поиск в ширину в Википедии Визуализатор алгоритма