Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
2_SAOD_-_Dinamicheskie_struktury_dannykh.doc
Скачиваний:
121
Добавлен:
21.03.2016
Размер:
1.66 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

procedureDFSR(Node:pNode);

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

var

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

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

begin

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

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

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

whileArc<>Nildobegin// поиск всех узлов, смежных с 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;

whileNode<>nildobegin// отметка всех узлов графа как непосещенных

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

end;

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

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

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

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

whilenotq.Emptydo begin// пока очередь не пуста

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

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

whileArc<>nildo 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.

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]