Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
САОД Part 1.DOC
Скачиваний:
43
Добавлен:
02.11.2018
Размер:
1.68 Mб
Скачать
  1. Обход ориентированного графа

При решении многих задач, связанных с графами, необходим эффективный способ систематического обхода всех узлов и дуг графа. Известны два способа обхода графов: обход в ширину и обход в глубину (в теории графов они называются поиском в глубину и поиском в ширину).

Способ обхода в глубину DFS (от depth-first search – поиск в глубину) составляет основу многих других эффективных алгоритмов работы с графами и состоит в следующем. Обход начинается с некоторого начального узла v графа g. Для каждого узла, смежного с узлом v и не посещавшегося ранее, рекурсивно применяется поиск в глубину. Когда все узлы, которые можно достичь из узла v, посещены, поиск заканчивается. Этот способ называется поиском в глубину, поскольку поиск непосещенных узлов идет в направлении вперед (вглубь) до тех пор, пока это возможно.

Для решения этой задачи необходимо переопределить тип tNode, включив в него дополнительное поле Visited логического типа – признак посещения узла. Начальное значение этого поля для всех узлов равно False. Приведенный ниже метод tOrGraph.DFS для обхода графа в глубину содержит внутреннюю рекурсивную процедуру DFSR, выполняющую обход в глубину от заданного узла Node. Посещение узла в данном методе заключается в выводе значения его содержательного поля Value в файл f.

procedure tOrGraph.DFS(StartNode: pNode; var f: Text);

// Обход в глубину, начиная с узла StartNode,

// с выводом значений узлов в файл f

procedure DFSR(Node:pNode);

// Внутренняя рекурсивная процедура обхода в глубину от узла Node

var

Arc:pArc; // дуга графа

NextNode:pNode; // узел, следующий за узлом Node

begin

Node^.Visited:=True; // отметка узла как посещенного

Write(f,Node^.Value,' > '); // посещение узла - вывод его значения в файл f

Arc:=Node^.ArcList; // первая дуга из списка дуг, инцидентных узлу Node

while Arc<>Nil do begin // поиск всех узлов, смежных с Node

NextNode:=Arc^.RearNode; // узел, смежный с узлом Node

if not NextNode^.Visited

then DFSR(NextNode); // узел не посещен - поиск от него

Arc:=Arc^.NextArc; // переход к следующему узлу, смежному с Node

end;

end; //procedure DFSR

var

Node:pNode;

begin

Node:=fHead;

while Node<>nil do begin // отметка всех узлов графа как непосещенных

Node^.Visited:=False; Node:=Node^.NextNode;

end;

DFSR(StartNode); Writeln(f);

end; // procedure tOrGraph.DFS

Способ обхода в ширину BFS (от breadth-first search – поиск в ширину) получил свое название из-за того, что при достижении во время обхода любого узла v далее рассматриваются все узлы, смежные с узлом v. После того как посещены и отмечены все не посещенные ранее узлы, смежные с узлом v, выбирается один из этих узлов и обход в ширину начинается от него, затем процесс повторяется для оставшихся смежных с v узлов. Для реализации этого алгоритма необходимо запоминать посещенные смежные с v узлы и, рассматривая их в порядке посещения, начинать процесс посещения всех узлов, смежных с ними. Для этой цели хорошо подходит такая структура данных как очередь (действительно, посещённые узлы становятся в очередь для продолжения процесса поиска от них).

procedure tOrGraph.BFS(StartNode: pNode; var f:Text);

// Обход в ширину, начиная с узла StartNode, с выводом значений узлов в файл f

var

Arc:pArc; // дуга графа

Node,NextNode:pNode; // очередной и следующий за ним узлы графа

q:tQueue; // экземпляр очереди с элементами типа pNode

begin

Node:=fHead;

while Node<>nil do begin // отметка всех узлов графа как непосещенных

Node^.Visited:=False; Node:=Node^.NextNode;

end;

q:= tQueue.Create; // создание экземпляра очереди

StartNode^.Visited:=True; // отметка начального узла как посещенного

Write(f,StartNode^.Value,' > '); // посещение начального узла

q.Insert(StartNode); // включение элемента StartNode в конец очереди

while not q.Empty do begin // пока очередь не пуста

Node:=q.Remove; // исключение первого элемента из очереди

Arc:=Node^.ArcList; // первая дуга из списка дуг, инцидентных узлу Node

while Arc<>nil do begin // поиск всех узлов, смежных с Node

NextNode:=Arc^.RearNode; // узел, смежный с узлом Node

if not NextNode^.Visited // если смежный узел не посещен,

then begin

NextNode^.Visited:=True; // то отметка его как посещенного,

Write(f,NextNode^.Value,' > '); // посещение узла

q.Insert(NextNode); // и включение его в конец очереди

end;

Arc:=Arc^.NextArc; // переход к следующему смежному с Node узлу

end;

end;

Writeln(f); q.Free; // удаление очереди

end; // procedure BFS

Для графа

обход в глубину дает последовательность узлов A, B, C, D, E, F, обход в ширину – A, B, D, C, E, F.

Если некоторые узлы графа при поиске от начального узла остались непосещенными, то выбирается один из них и поиск повторяется. Этот процесс продолжается до тех пор, пока обходом не будут охвачены все узлы графа.