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

Напомним, что расстоянием между двумя узлами n1 и n2 называется длина кратчайшего пути между этими узлами. Очевидно, что представляет интерес не только значение расстояния между двумя узлами, но и перечень узлов, входящих в кратчайший путь. Для решения этой задачи необходимо переопределить тип tNode, включив в него дополнительные поля: Dist – расстояние до данного узла от некоторого другого узла, PrevNode – указатель на узел, предшествующий текущему в кратчайшем пути. Начальное значение поля Dist для всех узлов равно нулю. Определяем расстояния от узла n1 до всех остальных узлов графа, для чего последовательно обходим граф от узла n1 по спискам смежности и в поле Dist узла, являющегося концом очередной дуги, записываем значение, равное сумме уже вычисленного расстояния до начального узла дуги плюс 1. Изменять значение поля Dist конечного узла дуги надо только в том случае, если оно меньше того значения, которое в этом поле хранится (расстояние – длина кратчайшего пути до узла). При каждом изменении значения поля Dist необходимо переопределять значение поля PrevNode, записывая в него указатель на тот узел, длина пути от которого до текущего узла оказалась меньшей.

Дополнительно необходимо хранить сведения об уже пройденных узлах (можно использовать поле Visited логического типа), чтобы не посещать их повторно. Начальное значение этого поля для всех узлов равно False. В основе алгоритма вычисления кратчайшего пути между узлами n1 и n2 лежит рекурсивный обход графа в глубину.

Метод tOrGraph.SPath возвращает строку с перечнем информационных полей узлов графа (типа tValue=Char), входящих в кратчайший путь между узлами Node1 и Node2. Длина кратчайшего пути (расстояние) равна длине этой строки, уменьшенной на 1.

function tOrGraph.SPath(Node1,Node2:pNode):String;

// Кратчайший путь между узлами Node1 и Node2

procedure PathFromNode(Node:pNode);

// Внутренняя рекурсивная процедура

// вычисления расстояния от узла Node до всех узлов графа

var

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

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

begin

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

Arc:=Node^.ArcList; // указатель на список смежности узла Node

while Arc<>nil do begin // пока не исчерпан список смежности узла Node

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

if not NextNode^.Visited

then begin // если узел NextNode еще не посещался,

NextNode^.Dist:=Node^.Dist+1; // то расстояние до него равно 1,

PathFromNode(NextNode); // продолжаем обход от него

NextNode^.PrevNode:=Node; // предыдущий узел для NextNode - Node

end

else // если узел NextNode уже посещался и,

if Node^.Dist+1<NextNode^.Dist // длина пути к нему через узел Node меньше

then begin

NextNode^.Dist:=Node^.Dist+1; // то изменяем длину пути на меньшую и

NextNode^.PrevNode:=Node; // запоминаем узел, через который пришли

end;

Arc:=Arc^.NextArc; // переход к следующей дуге списка смежности

end;

end; // procedure PathFromNode

var

Node:pNode; // текущий узел графа

S:string; // строка – перечень узлов кратчайшего пути

begin

Node:=fHead;

// установка начальных значений всех узлов графа

while Node<>nil do begin

Node^.Visited:=False; Node^.Dist:=0;

Node:=Node^.NextNode;

end;

// вычисление расстояний от узла Node1 до всех остальных

PathFromNode(Node1);

Node:=Node2; s:=NodeValue(Node2); // включение Node2 в начало строки

while Node<>Node1 do begin

// для всех узлов в кратч. пути от Node2 до Node1

Node:=Node^.PrevNode; // переход к узлу, предшествующему Node2

Insert(NodeValue(Node),S,1); // включение предш. узла в начало строки

end;

SPath:=S;

end; // function tOrGraph.SPath

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