2.6.1 Алгоритм пошуку у ширину
Алгоритм пошуку у ширину – один із базових алгоритмів, який є основою для багатьох інших алгоритмів на графах (наприклад алгоритм Дейкстри).
Допустимо, що заданий граф .і фіксована початкова вершина . Алгоритм пошуку у ширину знаходить всі доступні із вершини у порядку збільшення віддалі від . Віддалю між будь-якими двома вершинами графа є довжина (число ребер) найкоротшого шляху. У процесі пошуку із графа виокремлюється його частина, яка називається «» з коренем . Для кожної із вершин, які належать дереву пошуку у ширину, шлях із кореня у дереві буде найкоротшим. Алгоритм може застосовуватись як до неорієнтованих, так і до орієнтованих графів.
Для наочності вважатимемо, що у процесі роботи алгоритму вершини графа можуть бути білими, сірими і чорними. Спочатку всі вершини білі, але в процесі роботи алгоритму біла вершина може стати сірою, а сіра – чорною (але не навпаки). Зустрівши нову вершину (білу або сіру), алгоритм її зафарбовує. Це будуть ті вершини, які уже виявлені алгоритмом. Різниця між сірими і чорними вершинами використовується алгоритмом для керування порядком обходу: сірі вершини утворюють лінію «фронту», а чорні – «тил». Точніше, якщо , то і чорна, то - сіра або чорна.
Спочатку дерево пошуку вміщує тільки один корінь – початкову вершину . Як тільки алгоритм виявляє нову білу вершину , яка є суміжною з раніше знайденою вершиною , вершина разом з ребром долучається до дерева пошуку, стаючи дитиною вершини , а буде родичем вершини . Кожна вершина виявляється тільки один раз, так що двох родичів у неї не може бути. Поняття предка і нащадка визначається як завжди (потомки – це діти, діти дітей і т. д.). Рухаючись від кореня до вершина дерева пошуку, знаходимо всіх предків.
Наведена нижче процедура BFS (breadth-first search - пошук у ширину) використовує подання графа списком суміжних вершин. Для кожної вершини графа додатково зберігається її колір і її попередник . Якщо попередника немає (наприклад, або вершина ще не виявлена), то . Віддаль від до записується в поле Процедура використовує також чергу для зберігання множини сірих вершин.
BFS(G,s)
1 for (для кожної вершини )
2 color(v)=білий
3
4
5 end for
6 color(s)=сірий
7
8
9 Q={s}
10 while
11 v=head(Q)
12 for (для) всіх
13 if color(w)=білий
14 then color(w)=сірий
15 d(w)=d(w)+1
16
17 Enqueue(Q,w)
18 end if
19 end for
20 Dequeue(Q,w)
21 color(v)=чорний
22 end while
Процедура BFS використовує операцію добавляння вершини до черги і вона позначається як Enqueue та операцію видалення вершини із черги - Dequeue. Тут використано наступне провило: перший прийшов – першим обслужений. Черга має голову (head) і хвіст (tail). Вершина, що добавляється до черги стає у хвіст, а вершина, що вилучається із черги, знаходиться у її голові. На рис. 2.12 показано як можна реалізувати чергу, яка вміщує не більше ніж елемент, на базі масиву . Зберігається індекс - голова черги та - індекс вільної комірки, в яку буде поміщений наступний елемент, що долучається до черги. Черга складається із елементів масиву з номерами , , …, . Якщо = , то черга пуста. На початку роботи процедури маємо = =1.
Нижче наведені процедури добавлення елемента (вершини) до черги Enqueue(Q,w) та вилучення елемента (вершини) вершини із черги Dequeue.
Enqueue(Q,w)
1 Q(tail(Q))=w
2 if tail(Q)=length(Q)
3 then tail(Q)=1
4 else tail (Q)= tail (Q)+1
5 end if
Dequeue(Q,w)
1 w= Q(tail(Q))
2 if head(Q)=length(Q)
3 then head(Q)=1
4 else head(Q)=head(Q)+1
5 end if
6 return w
Рисунок 2.12 – Черга, що реалізована на базі масиву :
а) світло-сірі клітинки заняті елементами черги. В черзі знаходиться 5 елементів (позиції ); б) черга після виконання процедур Enqueue(Q,16), Enqueue(Q,4)і Enqueue(Q,7); в) черга після виконання процедури Dequeue(Q), яка повертає значення 16. Новою головою черги стає число 8
Повернемось тепер до основної процедури BFS. У рядках 1 – 4 вершини стають білими, а всі значення приймають значення і родичі всіх вершин об’являються NIL.Рядки 6 – 9 фарбують вершини у білий колір і виконують пов’язані з цим дії: у рядку 7 віддаль об’являється рівною нулю, а в рядку 8 говориться, що родичів у немає. І нарешті у рядку 9 вершина стає у чергу і з цього моменту черга буде вміщувати сірі вершини і тільки їх.
Основний цикл програми (рядки 10 – 22) виконується поки черга не пуста, тобто існують сірі вершини. У лінійці 11 така вершина поміщається у . Цикл for у рядках 12 – 19 проглядає всі суміжні з нею вершини. Виявивши серед них білу вершину , процедура BFS робить її сірою (рядок 14), об’являє її родичів (рядок 16) і встановлюємо віддаль рівною (рядок15). І нарешті, ця вершина добавляється у хвіст черги (рядок 17). Після цього вже можна видалити вершину із черги , перефарбувавши цю вершину у чорний колір (рядки 20 – 21).
Рис. 2.13 наочно демонструє виконання процедури BFS для неорієнтованого графа , у якого , .
Рисунок 2.13 – Використання процедури BFS для неорієнтованого графа
Вершини дерева, що формуються, показані сірим. Всередині кожної вершини вказано значення . Показано стан черги перед кожним повторенням циклу у рядках 10 – 22. Поряд з елементами черги вказані віддалі від кореня дерева.