Обход в ширину — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(Новая страница: «'''Поиск в ширину''' ('''BFS''', Breadth-first search) — метод обхода и разметки вершин графа. ==Алгоритм== ==…»)
 
Строка 1: Строка 1:
'''Поиск в ширину''' ('''BFS''', Breadth-first search) — метод обхода и разметки вершин графа.
+
'''Поиск в ширину''' ('''BFS''', Breadth-first search) — один из простейших алгоритмов обхода графа, являющийся основой для многих важных алгоритмов для работы с графами. Например, алгоритм [[Алгоритм Прима|Прима]] поиска минимального остовного дерева или алгоритм [[Алгоритм Дейкстры|Дейкстры]] поиска кротчайшего пути из одной вершины используют идеи, сходные идеями, используемыми при поиске в ширину.
  
 
==Алгоритм==
 
==Алгоритм==
  
 
===Общая идея===
 
===Общая идея===
Поиск в ширину реализуется с помощью структуры очередь. Для этого занесем в очередь исходную вершину. Затем, пока очередь не пуста, будем извлекать первый элемент из очереди и добавлять в конец все не посещенные смежные с ним вершины.  
+
Пусть задан граф <tex>G = (V, E)</tex> и выделена исходная вершина <tex>s</tex>. Алгоритм поиска в ширину систематически обходит все ребра <tex>G</tex> для "открытия" всех першин, достижимых из <tex>s</tex>, вычисляя при этом расстояние (минимальное количество ребер) от <tex>s</tex> до каждой достижимой из <tex>s</tex> вершины. Кроме того, в процессе обхода строится "дерево поиска в ширину" с корнем <tex>s</tex>, содержащее все достижимые вершины. Для каждой достижимой их <tex>s</tex> вершины <tex>v</tex> путь в дереве поиска в ширину соответствует кратчайшему поти от <tex>s</tex> до <tex>v</tex> в <tex>G</tex>.
 +
 
 +
Для отслеживания работы алгоритма поиск в ширину раскрашивает вершины графа в белый, серый и черный цвета. Изначально все вершины белые, и позже они могут стать серыми, а затем черными. Когда вершина '''открывается''' в процессе поиска, она окрашивается. Таким образом, серые и черные вершины — это вершины, которые уже были открыты, но алгоритм поиска в ширину по-разному работает с ними, чтобы обеспечить объявленный порядок обхода. Если <tex>(u, v) \in E</tex> и вершина <tex>u</tex> черного цвета, то вершина <tex>v</tex> либо серая, либо черная, т.е. все вершины, смежные с ней уже открыты. Серые вершины могут иметь белых соседей, представляя собой границу между открытыми и неоткрытыми вершинами.
 +
 
 +
Поиск в ширину стоит дерево поиска в ширину, которое изначально состоит из одного корня, которым является исходная вершина <tex>s</tex>. Если в процессе сканирования списка смежности уже открытое вершины <tex>u</tex> открывается белая вершина <tex>v</tex>, то вершина <tex>v</tex> и ребро <tex>(u, v)</tex> добавляются в дерево. При этом <tex>u</tex> является '''предшественником''' (predecessor), или '''родителем''' (parent), <tex>v</tex> в дереве поиска вширь. Посколько вершина модет быть открыта не более одного раза, она имеет не более одного родителя.  
  
 
=== Реализация===
 
=== Реализация===
Входные данные:
+
Приведенная ниже процедура поиска в ширину '''BFS''' предполагает, что входной граф <tex>G = (V, E)</tex> представлен при помощи списков смежности. Кроме того, поддерживаются дополнительные структуры данных в каждой вершине графа. Цвет каждой вершины <tex>u \in V</tex> хранится в переменной <tex>color[u]</tex>, а предшественник — в переменной <tex>p[u]</tex>. Если прежшественника у <tex>u</tex> нет, то <tex>p[u] =</tex> NIL. Расстояние от <tex>s</tex> до вершины <tex>u</tex>, вычисляемое алгоритмом, хранится в поле <tex>d[u]</tex>. Алгоритм использует очередь <tex>Q</tex> для работы с множеством серых вершин.
  vector < vector<int> > g; // граф, реализованный с помощью списка смежности
+
'''BFS'''(<tex>G</tex>, <tex>s</tex>)
  int n; // число вершин
+
  1  '''for''' (для) каждой вершины <tex>u \in V[G] - s</tex>
  int s; // стартовая вершина (вершины везде нумеруются с нуля)
+
  2    '''do''' <tex>color[u] \leftarrow</tex> WHITE
  // чтение графа
+
  3      <tex>d[u] \leftarrow \mathcal {1}</tex>
...
+
  4      <tex>p[u] \leftarrow</tex> NIL
 +
  5 <tex>color[s] \leftarrow</tex> GRAY
 +
  6  <tex>d[s] \leftarrow</tex> 0
 +
  7 <tex>p[s] \leftarrow</tex> NIL
 +
  8  <tex>Q \leftarrow</tex> Ø
 +
  9  ENQUEUE(<tex>Q</tex>, <tex>s</tex>)
 +
  10 '''while''' <tex>Q \ne </tex>Ø
 +
  11 '''do''' <tex>u \leftarrow</tex> DEQUEUE(<tex>Q</tex>)
 +
  12    '''for''' (для) каждой <tex>м \in Adj[u]</tex>
 +
  13      '''do''' '''if''' <tex>color[u] =</tex> WHITE
 +
  14        '''then''' <tex>color[v] \leftarrow</tex> GRAY
 +
  15              <tex>d[v] \leftarrow d[u] + 1</tex>
 +
  16              <tex>p[v] \leftarrow u</tex>
 +
  17              ENQUEUE(<tex>Q</tex>, <tex>v</tex>)
 +
  18    <tex>color[u] \leftarrow</tex>BLACK
  
Сам обход:
+
== Анализ ==
queue<int> q;
+
Оценим время работы для входного графа <tex>G = (V, E)</tex>. После инициализации ни одна вершина не окрашивается в белый цвет, поэтому проверка в строке 13 гарантирует, что каждая вершина вносится в очередь не более одного раза, а следовательно, и удаляется из очереди она не более одного раза. Операции внесения в очередь и удаления из нее требуют <tex>O(1)</tex> времени, так что общее время операций с очередью составляет <tex>O(V)</tex>. Поскольку каждый список смежности сканируется только при удалении соответствующей вершины из очереди, каждый список сканируется не более одного раза. Так как сумма длин всех списков смежности равна <tex> \Theta (E) </tex>, общее время, необходимое для сканирования списков, равно <tex>O(E)</tex>. Накладные расходы на инициализацию равны <tex>O(V)</tex>, так что общее время работы процедуры '''BFS''' составляет <tex>O(V + E)</tex>. Таким образом, время работы поиска в ширину линейно зависит от размера представления графа <tex>G</tex> с использованием списков смежности.
q.push (s);
 
vector<bool> used (n);
 
used[s] = true;
 
while (!q.empty()) {
 
int v = q.front();
 
q.pop();
 
for (size_t i=0; i<g[v].size(); ++i) {
 
int to = g[v][i];
 
if (!used[to]) {
 
used[to] = true;
 
q.push (to);
 
}
 
}
 
}
 
== Практические применения ==
 
* Волновой алгоритм в трассировке печатных плат;
 
* Поиск увеличивающего пути в Форда-Фалкерсона алгоритм|алгоритме Форда-Фалкерсон (алгоритм Эдмондса-Карпа)
 
  
 
== Литература ==
 
== Литература ==
* Ананий В. Левитин Глава 5. Метод уменьшения размера задачи: Поиск в ширину // Алгоритмы: введение в разработку и анализ = Introduction to The Design and Analysis of Aigorithms. — М.: «Вильямс», 2006. — С. 215-218. — ISBN 0-201-74395-7
 
 
*Томас Х. Кормен и др. Алгоритмы: построение и анализ = INTRODUCTION TO ALGORITHMS. — 2-е изд. — М.: «Вильямс», 2006. — С. 1296. — ISBN 0-07-013151-1
 
*Томас Х. Кормен и др. Алгоритмы: построение и анализ = INTRODUCTION TO ALGORITHMS. — 2-е изд. — М.: «Вильямс», 2006. — С. 1296. — ISBN 0-07-013151-1

Версия 00:31, 16 января 2011

Поиск в ширину (BFS, Breadth-first search) — один из простейших алгоритмов обхода графа, являющийся основой для многих важных алгоритмов для работы с графами. Например, алгоритм Прима поиска минимального остовного дерева или алгоритм Дейкстры поиска кротчайшего пути из одной вершины используют идеи, сходные идеями, используемыми при поиске в ширину.

Алгоритм

Общая идея

Пусть задан граф [math]G = (V, E)[/math] и выделена исходная вершина [math]s[/math]. Алгоритм поиска в ширину систематически обходит все ребра [math]G[/math] для "открытия" всех першин, достижимых из [math]s[/math], вычисляя при этом расстояние (минимальное количество ребер) от [math]s[/math] до каждой достижимой из [math]s[/math] вершины. Кроме того, в процессе обхода строится "дерево поиска в ширину" с корнем [math]s[/math], содержащее все достижимые вершины. Для каждой достижимой их [math]s[/math] вершины [math]v[/math] путь в дереве поиска в ширину соответствует кратчайшему поти от [math]s[/math] до [math]v[/math] в [math]G[/math].

Для отслеживания работы алгоритма поиск в ширину раскрашивает вершины графа в белый, серый и черный цвета. Изначально все вершины белые, и позже они могут стать серыми, а затем черными. Когда вершина открывается в процессе поиска, она окрашивается. Таким образом, серые и черные вершины — это вершины, которые уже были открыты, но алгоритм поиска в ширину по-разному работает с ними, чтобы обеспечить объявленный порядок обхода. Если [math](u, v) \in E[/math] и вершина [math]u[/math] черного цвета, то вершина [math]v[/math] либо серая, либо черная, т.е. все вершины, смежные с ней уже открыты. Серые вершины могут иметь белых соседей, представляя собой границу между открытыми и неоткрытыми вершинами.

Поиск в ширину стоит дерево поиска в ширину, которое изначально состоит из одного корня, которым является исходная вершина [math]s[/math]. Если в процессе сканирования списка смежности уже открытое вершины [math]u[/math] открывается белая вершина [math]v[/math], то вершина [math]v[/math] и ребро [math](u, v)[/math] добавляются в дерево. При этом [math]u[/math] является предшественником (predecessor), или родителем (parent), [math]v[/math] в дереве поиска вширь. Посколько вершина модет быть открыта не более одного раза, она имеет не более одного родителя.

Реализация

Приведенная ниже процедура поиска в ширину BFS предполагает, что входной граф [math]G = (V, E)[/math] представлен при помощи списков смежности. Кроме того, поддерживаются дополнительные структуры данных в каждой вершине графа. Цвет каждой вершины [math]u \in V[/math] хранится в переменной [math]color[u][/math], а предшественник — в переменной [math]p[u][/math]. Если прежшественника у [math]u[/math] нет, то [math]p[u] =[/math] NIL. Расстояние от [math]s[/math] до вершины [math]u[/math], вычисляемое алгоритмом, хранится в поле [math]d[u][/math]. Алгоритм использует очередь [math]Q[/math] для работы с множеством серых вершин.

BFS([math]G[/math], [math]s[/math])
  1  for (для) каждой вершины [math]u \in V[G] - s[/math]
  2    do  [math]color[u] \leftarrow[/math] WHITE
  3      [math]d[u] \leftarrow \mathcal {1}[/math]
  4      [math]p[u] \leftarrow[/math] NIL
  5  [math]color[s] \leftarrow[/math] GRAY
  6  [math]d[s] \leftarrow[/math] 0
  7  [math]p[s] \leftarrow[/math] NIL
  8  [math]Q \leftarrow[/math] Ø
  9  ENQUEUE([math]Q[/math], [math]s[/math])
  10 while [math]Q \ne [/math]Ø
  11  do [math]u \leftarrow[/math] DEQUEUE([math]Q[/math])
  12     for (для) каждой [math]м \in Adj[u][/math]
  13       do if [math]color[u] =[/math] WHITE
  14         then [math]color[v] \leftarrow[/math] GRAY
  15              [math]d[v] \leftarrow d[u] + 1[/math]
  16              [math]p[v] \leftarrow u[/math] 
  17              ENQUEUE([math]Q[/math], [math]v[/math])
  18     [math]color[u] \leftarrow[/math]BLACK

Анализ

Оценим время работы для входного графа [math]G = (V, E)[/math]. После инициализации ни одна вершина не окрашивается в белый цвет, поэтому проверка в строке 13 гарантирует, что каждая вершина вносится в очередь не более одного раза, а следовательно, и удаляется из очереди она не более одного раза. Операции внесения в очередь и удаления из нее требуют [math]O(1)[/math] времени, так что общее время операций с очередью составляет [math]O(V)[/math]. Поскольку каждый список смежности сканируется только при удалении соответствующей вершины из очереди, каждый список сканируется не более одного раза. Так как сумма длин всех списков смежности равна [math] \Theta (E) [/math], общее время, необходимое для сканирования списков, равно [math]O(E)[/math]. Накладные расходы на инициализацию равны [math]O(V)[/math], так что общее время работы процедуры BFS составляет [math]O(V + E)[/math]. Таким образом, время работы поиска в ширину линейно зависит от размера представления графа [math]G[/math] с использованием списков смежности.

Литература

  • Томас Х. Кормен и др. Алгоритмы: построение и анализ = INTRODUCTION TO ALGORITHMS. — 2-е изд. — М.: «Вильямс», 2006. — С. 1296. — ISBN 0-07-013151-1