Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции ТЭИС.doc
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
11.22 Mб
Скачать

7.3.Поиск на графах

На практике часто возникают задачи, связанные с прохождением по вершинам графа. Например, необходимо ответить на вопрос: достижима ли вершина d из вершины r? То есть, существует ли путь из вершины r в вершину d.

Для ответа на вопрос, достижима вершина d из вершины r или нет, необходимо организовать обход вершин графа, начиная из вершины r. Если во время обхода мы встретим вершину d, следовательно, вершина d достижима из вершины r, в противном случае - d из r не достижима.

Существует два способа организации обхода: поиск в глубину и поиск в ширину.

7.3.1.Поиск в глубину

Поиск в глубину на графе G=(V,E) осуществляется по следующим правилам:

  1. Начинаем поиск с начальной вершины r. В качестве текущей вершины v берем вершину r.

  2. Из текущей вершины v двигаемся в любую, ранее не пройденную вершину w, если такая вершина найдется (если вершины w нет, см. пункт 3). Запоминаем дугу, по которой мы попали в вершину w. В качестве текущей вершины v берем вершину w.

  3. Если из вершины v мы не можем попасть в ранее не пройденную вершину w, то возвращаемся в вершину x, из которой мы попали в v. В качестве текущей вершины v берем вершину x.

  4. Процесс поиска (пункты 2, 3) заканчивается, когда мы пытаемся вернуться назад из вершины, с которой начался поиск (вершина r).

Поиск в глубину проиллюстрирован на рис. 7.15.

Алгоритм поиска в глубину представлен укрупненной блок-схемой на рис.7.16.

В алгоритме поиска в глубину требуется определять номер неокрашенной вершины (k) смежной вершине v (см. рис.7.16). Данные действия проще всего реализовать, когда исходный граф хранится матрицей смежности или упакованной матрицей смежности (см. разд.2.4.10).

В алгоритме используются операции со стеком. Реализация стека может быть любой: на массиве, с помощью указателей или курсоров. Наиболее рационально реализовать стек на массиве (см. разд.2.4.6). Это связано с тем, что максимальная глубина стека не может превышать числа вершин графа.

Для окраски вершин графа (см. рис.7.16, оператор «Окрасить вершину K») следует использовать множество. В данное множество заносятся окрашенные вершины. Если в алгоритмическом языке стандартный тип «множество» отсутствует, то для реализации множества можно использовать массив M длины n, где n - число элементов множества. Элементами массива M являются числа 0 и 1, причем, M[i]=0, если i-ый элемент принадлежит множеству и M[i]=1, если i-ый элемент не принадлежит множеству. В этом случае оператор «Окрасить вершину K» реализуется следующим образом: M[K]:=1.

Отметим, что дуги, по которым осуществляется обход графа (окрашенные дуги) в результате выполнения алгоритма поиска, образуют ориентированное дерево с корнем в начальной вершине. Поэтому для окраски дуги графа (см. рис.7.16, оператор «Окрасить дугу (v,K)») следует использовать массив P, хранящий ориентированное дерево (см. разд. 2.4.8). В этом случае оператор «Окрасить дугу (v,K)» реализуется следующим образом: P[K]:=v.

Полностью реализация алгоритма поиска в глубину представлена в листинге 7.9.

Листинг 7.9

Const

maxN =100; {Максимальное число вершин графа}

Type

tGraf=array[1.. maxN,1.. maxN] of boolean; {Тип для хранения матрицы смежности}

tO= array[1.. maxN] of boolean; {Тип для хранения признаков окраски вершин}

tP=array[1.. maxN] of integer; {Тип для хранения дерева из окрашенных дуг}

Здесь должно быть описание типа STACK – стек и операторов

NULLSTACK, EMPTYSTACK, PUSH, POP, TOP (см. Разд.2.4.5 и 2.4.6)

Var

A:tGraf; {Матрица смежности}

N:integer; {Число вершин}

Start:integer; {Начальная вершина}

P:tP; {Дерево из окрашенных дуг}

Procedure PoiskGl(A:tGraf; N,Start:integer; var O:tO; var P:tP); {Поиск в глубину}

var i,v,k:integer; S:STACK;

function SmVer(v:integer):integer;

{Возвращает номер неокрашенной вершины смежной вершине v, если такая вершина есть,

и 0 – в противном случае}

var i:integer;

begin

i:=1;

while not((i>N)or(A[v,i]=1)and(O[i]=false)) do i=i+1;

if i>N then SmVer:=0 else SmVer:=i

end;

begin

for i:=1 to N do {Все вершины и дуги графа не окрашены}

begin O[i]:=false; P[i]:=0 end;

EMPTYSTACK(S); {S <=пустой стек}

PUSH(Start,S); {S<= начальная вершина }

v:=Start; {v= начальная вершина }

O[v]:=true; {Окрасить вершину v}

While not EMPTY(S) do {Стек не пуст?}

begin

k:=SmVer(v); {k – номер неокрашенной вершины смежной вершине v,

если такая вершина есть, и k=0, в противном случае }

if k<>0 then

begin

O[k]:=true; {Окрасить вершину k}

P[k]:=v; {Окрасить дугу (v,k)}

PUSH(k,S); {S<=k}

v:=k;

end

else

begin

POP(S); {Удалить вершину стека S}

if not EMPTY(S) then {Стек S не пуст ?}

V:=TOP(S) {v=вершина стека S}

end

end

end;

Далее должен быть ввод графа, вызов процедуры PoiskGl и вывод результатов поиска.