- •Тема 2. ЕТАПИ РОЗВИТКУ ТЕОРІЇ АЛГОРИТМІВ ТА ЇЇ ЗАСНОВНИКИ
- •Тема 3. МОДЕЛІ ОБЧИСЛЕНЬ
- •Тема 4. ПОНЯТТЯ СТРУКТУР ДАНИХ
- •Тема 5 СТРУКТУРНІСТЬ ДАНИХ І ТЕХНОЛОГІЯ ПРОГРАМУВАННЯ
- •Тема 6. ІНФОРМАЦІЙНА МОДЕЛЬ
- •Тема 7. ПОКАЖЧИКИ ТА ОПЕРАЦІЇ НАД НИМИ
- •Тема 8. ФІЗИЧНА СТРУКТУРА ПОКАЖЧИКА
- •Тема 9. ПРЕДСТАВЛЕННЯ ПОКАЖЧИКІВ У МОВАХ ПРОГРАМУВАННЯ
- •Тема 10. ВИДІЛЕННЯ ТА ЗВІЛЬНЕННЯ ДИНАМІЧНОЇ ПАМ'ЯТІ
- •Тема 11. ПРИКЛАДИ РОБОТИ З ДИНАМІЧНИМИ ЗМІННИМИ
- •Тема 12. ЗАГАЛЬНА ХАРАКТЕРИСТИКА СПИСКОВИХ СТРУКТУР ДАНИХ
- •Тема 13. ЗВ’ЯЗНЕ ПРЕДСТАВЛЕННЯ ДАНИХ В ПАМ'ЯТІ КОМП’ЮТЕРА
- •Тема 14. СТЕКИ
- •Тема 15. МАШИННЕ ПРЕДСТАВЛЕННЯ СТЕКА І РЕАЛІЗАЦІЯ ОПЕРАЦІЙ
- •Тема 16. ЧЕРГИ
- •Тема 17. МАШИННЕ ПРЕДСТАВЛЕННЯ ЧЕРГИ. ЧЕРГИ З ПРІОРИТЕТАМИ. ДЕКИ.
- •Тема 18. ЛІНІЙНІ СПИСКИ
- •Тема 19: ДВОНАПРЯМЛЕНІ ЛІНІЙНІ СПИСКИ
- •Тема 20. ДЕРЕВА. СТВОРЕННЯ ТА ОБХІД БІНАРНОГО ДЕРЕВА
- •Тема 21: ЕЛЕМЕНТИ ТА ВЛАСТИВОСТІ БІНАРНОГО ДЕРЕВА
- •Тема 22. ОПЕРАЦІЇ З ВУЗЛАМИ ДЕРЕВА
- •Тема 23: АЛГОРИТМИ ВИЗНАЧЕННЯ ВЛАСТИВОСТЕЙ БІНАРНОГО ДЕРЕВА
- •Тема 24. ПОНЯТТЯ ГРАФА ТА ЙОГО ЗОБРАЖЕННЯ В ПАМ'ЯТІ КОМП'ЮТЕРА
- •Тема 26. ОБХІД ГРАФУ: ПОШУК ВГЛИБИНУ
- •Тема 27. ОБХІД ГРАФУ: ПОШУК УШИР
- •Тема 28. КЛАСИЧНІ АЛГОРИТМИ СОРТУВАННЯ ОДНОРІДНИХ ДАНИХ
- •Тема 29. ШВИДКІ АЛГОРИТМИ СОРТУВАННЯ ОДНОРІДНИХ ДАНИХ
- •Тема 30. КЛАСИЧНІ АЛГОРИТМИ ПОШУКУ ДАНИХ ЗА ЗАДАНИМИ КРИТЕРІЯМИ
- •Тема 31. КЛАСИФІКАЦІЯ КРИТЕРІЇВ ПОШУКУ ДАНИХ У МАСИВАХ
- •Тема 32. КРИПТОГРАФІЧНІ ЗАСОБИ ЗАХИСТУ ІНФОРМАЦІЇ
- •Тема 33. ПРОБЛЕМИ І ПЕРСПЕКТИВИ КРИПОТГРАФІЧНИХ СИСТЕМ
- •Тема 34. АЛГОРИТМИ ШИФРУВАННЯ
- •Тема 36. ПОКАЗНИКИ СКЛАДНОСТІ АЛГОРИТМІВ
Тема 27. ОБХІД ГРАФУ: ПОШУК УШИР
За алгоритмом пошуку вшир здійснюється обхід графу в порядку збільшення відстані від стартової вершини. Відстань між вершинами a і b вважається рівною кілкості ребер на найкоротшому шляху від a до b. Отже, спочатку переглядається стартова вершина, потім – суміжні з нею вершини, що входять до списку перегляду. Кожні ітерація алгоритму полягає в послідовному виборі всіх вершин зі списку перегляду і додаванні до цого списку вершин, що є суміжними з вибраними. При цому вершини не можуть переглядатися двічі, а тому під час перегляду вершину слід позначати. Позначені вершини надалі не розглядаються.
Список перегляду найзручніше зберігати у вигляді черги. При перегляді вершини всі суміжні з нею непозначені вершини додаються до черги, а сама вершина з черги вилучається. Пошук виконується доти, доки не буде знайдено кінцевої вершини або список перегляду не стане порожнім.
Часова складність пошуку вшир, так само як і пошуку вглибину, становить О(n+m), де n – кількість вершин графу, а m – кількість його ребер. Справді, кожна вершина додається до черги і вилучається з неї лише один раз, а кількість ітерацій циклу пошуку суміжних вершин з точністю до сталого множника дорівнює кількості ребер графу.
Приклад. Алгоритм пошуку вшир використовується для знаходження шляху від стартової до кінцевої вершини в неорієнтованому графі. Ініціалізація масиву вершин даними, що зчитані з текстового файлу. Виконується у процедурі Init, з якої викликається процедура зв’язування суміжних вершин LinkVertex. Слід звернути увагу на те, що одному ребру відповідають два зв’язки між вершинами, оскільки алгоритм розглядається для неорієнтованого графу.
Пошук ушир вершини finish, що розпочинається з вершини start, виконує процедура BreadFirstSearch. Усі вершини, що є суміжними з поточною і не були позначені, додаються до черги за допомогою процедури AddList. Черга переглядається, починаючи від вершини PCur. Тому виконання оператора PCur:=PCur^.Next є дією, логічно еквівалентною видаленняю вершини з черги. У разі знаходження кінцевої вершини або вичерпування всіх можливостей пошуку, чергу слід очистити за допомогою процедури Clear. Нарешті, рекурсивна процедура Output здійснює виведення знайденого шляху. Для посилання на попередню вершину використовується покажчик Prev.
program yrok12_2; |
{пошук ушир} |
|
{$APPTYPE CONSOLE} |
|
|
uses SysUtils; |
|
|
type |
|
|
PtrVer = ^TVer; |
{тип покажчика на вершину} |
|
TVer = record |
{тип вершини графу} |
|
vertex: array[1..50] of PtrVer; |
{масив покажчиків на суміжні вершини графу} |
|
k, |
{кількість суміжних вершин} |
|
number : integer; |
{номер вершини} |
|
mark : boolean; |
{ознака відвідування вершини} |
|
end; |
|
|
PElem = ^TElem; |
{тип покажчика на елемент черги} |
|
TElem = record |
{тип елемента черги} |
|
PVer : PtrVer; |
{покажчик на поточну вершину} |
|
PFrom: PElem; |
{покажчик на попередню вершину} |
|
Prev, |
{покажик на попередній елемент черги} |
|
Next : PElem; |
{покажчик на наступний елемент черги} |
|
end; |
|
|
var PBeg, PEnd, |
{покажчики на початок та кінець черги} |
97
PCur : PElem; |
{покажчик на поточний елемент черги} |
t : text; |
{ файлова змінна } |
key : char; |
{ символ обраної користувачем дії } |
start,finish : integer;{ номери стартової та кінцевої вершин обходу графу } a : array[1..50] of PtrVer; { масив покажчиків на вершини графу }
n : integer; { кількість вершин графу } { Встановлення зв’язків між вершинами графу } procedure LinkVertex(var v,u: PtrVer);
begin
inc(v^.k); |
v^.vertex[v^.k]:=u; |
{включити u в список суміжності v} |
|
inc(u^.k); |
u^.vertex[u^.k]:=v; |
{ включити v в список суміжності u } |
|
end; |
|
|
|
{Ініціалізація графу з файлу} |
|||
procedure Init; |
|
|
|
var i, {параметр циклу} |
|
||
iv,iu: integer; |
{номери суміжних вершин} |
||
Ver: PtrVer; |
{покажчик на вершину графу} |
||
begin |
|
|
|
assign(t, 'graph.txt'); |
|
|
|
reset(t); |
|
{відкриття файлу для читання суміжних вершин} |
|
readln(t,n); |
{читання кілкості вершин графу} |
||
for i:=1 to n do |
{створення масиву покажчиків на вершини графу} |
||
begin |
|
|
|
new(Ver); |
{виділення пам'яті для покажчика на вершину} |
||
Ver^.number:=i; |
{визначення номеру вершини} |
||
Ver^.k:=0; |
{задання кількості суміжних вершин} |
||
a[i]:=Ver; |
{запис покажчика на вершину в масив} |
||
end; |
|
|
|
while not eof(t) do |
{поки не досягнуто кінця файлу} |
||
begin |
|
|
|
readln(t,iv,iu); |
{читання номерів суміжних вершин} |
||
LinkVertex(a[iv],a[iu]); {зв’язування вершин} |
|||
end; |
|
|
|
close(t); |
|
{закриття файлу} |
|
end; |
|
|
|
{Додавання елементу до черги} procedure AddList(v : PtrVer; q : PElem);
{v – покажчик на вершину, що додається до черги} {q – покажчик на попередній елемент черги}
var p : PElem; {поточний покажчик} begin
new(p); |
{виділення пам'яті для елемента черги} |
p^.PVer:=v; |
{покажчик на поточну вершину} |
p^.PFrom:=q; |
{покажчик на попередню суміжну вершину} |
p^.Prev:=PEnd^.Prev; {зв’язування поточного і кінцевого елементів черги} p^.Next:=PEnd;
PEnd^.Prev^.Next:=p; {}
98
PEnd^.Prev:=p; |
{} |
end; |
|
{Видалення елемента з черги} procedure DelList(e : pElem);
{е – покажчик на елемент, що видаляється}
var p : PElem; |
|
|
begin |
|
|
if e = nil then exit; |
{якщо елемент порожній, то – вихід з програми} |
|
e^.Next^.Prev:=e^.Prev; |
{переадресація покажчика } |
|
e^.Prev^.Next:=e^.Next; |
|
|
dispose(e); |
{вивільнення пам'яті з-під елемента} |
|
end; |
|
|
{Виведення поточного елемента черги} |
||
procedure Output(e : pElem); |
|
|
begin |
|
|
if e = nil then exit; |
{ якщо елемент порожній, то – вихід з програми } |
|
output(e^.PFrom); |
{виведення решти елементів черги} |
if e^.PVer^.number <> finish |
|
|
|
then write(e^.PVer^.number,' -> ') |
{якщо елемент є останнім} |
||
else write(e^.PVer^.number,' '); |
{ якщо елемент не є останнім } |
||
end; |
|
|
|
{Видалення черги} |
|
|
|
procedure Clear; |
|
|
|
var PCurrent, PDel : PElem; |
|
|
|
begin |
|
|
|
PCurrent:=PBeg^.Next; |
|
|
|
while PCurrent <> PEnd do |
{поки не досягнуто кінця черги} |
||
begin |
|
|
|
PDel:=PCurrent; |
|
{покажчик на елемент, що видаляється} |
|
PCurrent:=PCurrent^.Next; |
{переадресація покажчика на наступний елемент} |
||
DelList(PDel); |
{видалення елементу} |
||
end; |
|
|
|
end;
{Пошук ушир}
procedure BreadFirstSearch; var i : integer;
begin clrscr;
writeln('<<<<Bread First Search>>>>'); writeln('**************************'); write('inicial vertex : '); readln(start); write('terminal vertex: '); readln(finish);
AddList(a[start], nil); |
{додавання вершини до черги} |
||
for i:=1 to n do a[i]^.mark:=false; |
{позначення вершин графу, як такі, що не відвідані} |
||
PCur:=PBeg^.Next; |
{вибір початку черги} |
||
while PCur <> PEnd do |
{поки не досягнуто кінці черги} |
||
begin |
|
|
|
99
PCur^.PVer^.mark:=tr ue; {позначення відвіданої вершини графу}
if PCur^.PVer^.number = finish then |
{якщо вершина є останньою в черзі} |
|
begin |
|
|
write('Path : >>'); |
|
|
output(PCur); |
{виведення черги} |
|
clear; |
{очищення черги} |
|
readln; |
|
|
exit; |
{вихід з процедури} |
|
end; |
|
|
{ якщо вершина не є ост анньою в черзі } |
|
|
for i:=1 to PCur^.PVer ^.k do |
|
|
begin |
|
|
if not PCur^.PVer^.v ertex[i]^.mark |
{якщо вершина не познач ена} |
|
then AddList(PCur^.PVer^.vertex[i],PCur); |
||
end; |
|
|
PCur:=PCur^.Next; |
{перехід до наступної вершини} |
|
end; |
|
|
writeln('<<< Path not foun d >>>');
readln;
clear; { очищення черги } end;
{Основний блок програми} begin
new(PBeg); new(PEnd); PBeg^.Prev:=nil; PBeg^. Next:=PEnd; PEnd^.Prev:=PBeg; PEndd^.Next:=nil; init;
repeat
writeln('Number of vertexes = ',n); writeln('***********************'); writeln('press <Enter> to solution'); writeln('<x> - to exit');
readln(key); case key of
#13: BreadFirstSearch; ‘x’: halt;
end; until false; end.
Для даних: 5
13
14
23
25
34
отримано наступний рез ультат:
100