Поиск в ширину (волновой алгоритм)
Этот алгоритм поиска в графе также называют волновым алгоритмом из-за того, что обход графа идет по принципу распространения волны. Волна растекается равномерно во все стороны с одинаковой скоростью. На i-ом шаге будут помечены все вершины, достижимые за i ходов, если ходом считать переход из одной вершины в другую.
procedure WidthSearch(v: integer);
var
Delayed: array[1..n] of integer; {Очередь}
Count, {Хвост очереди}
Head: integer; {Голова очереди}
Current, j: integer;
begin
Count := 1; Head := 0; Delayed[Count] := v;
Visited[v] := true;
repeat
Head := Head +1; Current := Delayed[Head];
for каждой вершины y, смежной с Current do
if not Visited[y] then begin
Count := Count + 1;
Delayed[Count] := Graph[y];
Visited[y] := true;
end;
until Count = Head;
end;
begin
while есть непомеченные вершины do begin
v := любая непомеченная вершина;
WidthSearch(v);
end;
end.
Листинг 5.1 – Поиск в ширину
Листинг 5.2 – Поиск в ширину
Данный алгоритм может быть описан и так. Пусть задан граф G = (V, Е) и фиксирована начальная вершина(source
vertex) s. Алгоритм поиска в ширину перечисляет все достижимые из s (если
идти по рёбрам) вершины в порядке возрастания расстояния от s. Расстоя-
нием считается длина (число рёбер) кратчайшего пути. В процессе поиска из
графа выделяется часть, называемая «деревом поиска в ширину» с корнем s.
Она содержит все достижимые из s вершины (и только их). Для каждой из
них путь из корня в дереве поиска будет одним из кратчайших путей (из
начальной вершины) в графе. Алгоритм применим и к ориентированным, и к
неориентированным графам.
Название объясняется тем, что в процессе поиска мы идём вширь, а не
вглубь (сначала просматриваем все соседние вершины, затем соседей соседей
и т.д.).
Для наглядности мы будем считать, что в процессе работы алгоритма вер-
шины графа могут быть белыми, серыми и чёрными. Вначале они все белые, но в ходе работы алгоритма белая вершина может стать серой, а серая – чёрной
(но не наоборот). Повстречав новую вершину, алгоритм поиска красит её, так
что окрашенные (серые или чёрные) вершины – это в точности те, которые
уже обнаружены. Различие между серыми и чёрными вершинами используется
алгоритмом для управления порядком обхода: серые вершины образуют «линию
фронта», а чёрные – «тыл». Более точно, поддерживается такое свойство: если
(и, v) Е и и чёрная, то v – серая или чёрная вершина. Таким образом, только
серые вершины могут иметь смежные необнаруженные вершины.
Вначале дерево поиска состоит только из корня – начальной вершины s.
Как только алгоритм обнаруживает новую белую вершину v, смежную с ранее
найденной вершиной и, вершина v (вместе с ребром (u, v)) добавляется к де-
реву поиска, становясь ребёнком (child) вершины и, а и становится родителем
(parent) v. Каждая вершина обнаруживается только однажды, так что двух ро-
дителей у неё быть не может. Понятия предка (ancestor) и потомка (descendant)
определяются как обычно (потомки – это дети, дети детей, и т. д.). Двигаясь
от вершины ккорню, мы проходим всех её предков.
Приведённая ниже процедура BFS (breadth-first search – поиск в ширину)
использует представление графа G = (V, Е) списками смежных вершин. Для
каждой вершины и графа дополнительно хранятся её цвет color[u]и её пред-
шественник [u]. Если предшественника нет (например, если и = s или и ещё
не обнаружена), [u] = NIL. Кроме того, расстояние от s до и записывается
в поле d[u]. Процедура использует также очередь Q(FIFO) для
хранения множества серых вершин.
В строках 1 – 4 все вершины становятся белыми, все значения d бесконечны-
ми, и родителем всех вершин объявляется NIL. Строки 5 – 8 красят вершину s в
серый цвет и выполняют связанные с этим действия: в строке 6 расстояние d[s]
объявляется равным 0, а в строке 7 говорится, что родителя у s нет. Наконец,
в строке 8 вершина s помещается в очередь Q, и с этого момента очередь будет
содержать все серые вершины и только их.
Основной цикл программы (строки 9 – 18) выполняется, пока очередь непус-
та, то есть существуют серые вершины (вершины, которые уже обнаружены,
но списки смежности которых ещё не просмотрены). В строке 10 первая такая
вершина помещается в и. Цикл for в строках 11 – 16 просматривает все смежные
с ней вершины. Обнаружив среди них белую вершину, мы делаем её серой
(строка 13), объявляем и её родителем (строка 15) и устанавливаем расстояние
равным d[u] + 1 (строка 14). Наконец, эта вершина добавляется в хвост очере-
ди Q (строка 16). После этого уже можно удалить вершину и из очереди Q,
перекрасив эту вершину в черный свет (строки 17 – 18).
Рисунок 5.1 – Поиск в ширину