Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Теория алгоритмов.doc
Скачиваний:
7
Добавлен:
29.08.2019
Размер:
1.49 Mб
Скачать

Зміст

Вступ 2

Алгоритм Прима 4

Алгоритм Крускала 7

Порівняльний аналіз дії алгоритмів на тестовому прикладі 10

Програмна реалізація алгоритмів 13

Завдання для самостійної роботи 20

Список літератури 28

Вступ

Нехай G = (V, Е) — зв'язний граф, у якому кожне ребро (u,v ) позначено числом c(u, v), що називається вартістю ребра. Остовним деревом графа G називається вільне дерево, що містить всі вершини V графа G. Вартість остовного дерева обчислюється як сума вартостей всіх ребер, що входять у це дерево.

Типове застосування остовних дерев мінімальної вартості можна знайти при розробці комунікаційних мереж. Тут вершини графа представляють міста, ребра - можливі комунікаційні лінії між містами, а вартість ребер відповідає вартості комунікаційних ліній. У цьому випадку остовне дерево мінімальної вартості представляє комунікаційну мережу, що поєднує всі міста комунікаційними лініями мінімальної вартості.

Поставлене завдання: маючи на вході граф G, одержати на виході його остовне дерево мінімальної вартості, використати алгоритми Крускала й Прима. Порівняти використовувані алгоритми.

Існують різні методи побудови остовних дерев мінімальної вартості. Багато хто з них ґрунтуються на наступній властивості остовних дерев мінімальної вартості. Нехай G = (V, Е) — зв'язний граф із заданою функцією вартості, що задана на множині ребер. Позначимо через U підмножину вершин V. Якщо (і, v) — таке ребро найменшої вартості, що й належить U і v належить V \ U, тоді для графа G існує остовное дерево мінімальної вартості, що містить ребро (і, v).

Існують два популярних алгоритми побудови остовного дерева мінімальної вартості для позначеного графа G = (V, Е), основані на описаній властивості: Прима й Крускала. Обидва алгоритми відповідають «жадібній» стратегії: на кожному кроці вибирається локально найкращий варіант.

Алгоритм Прима

У цьому алгоритмі будується множина вершин U, з якого "виростає" остовне дерево. Нехай V={1, 2, ..., n }. Спочатку U={1}. На кожному кроці алгоритму обираємо ребро найменшої вартості (u, v) таке, що u U і v V\U, потім вершина v переноситься з множини V\U у множину U. Цей процес триває доти, поки множина U не стане рівною множині V.

Ескіз алгоритму:

procedure Prim ( G: граф; var P: множина ребер );

var

U: множина вершин;

u,v- вершини;

begin

P:= ;

U:= {1};

while U <> V do begin

знаходження ребра (u,v) найменшої вартості й такого, що u U і v V\U;

P:= P {(u,v}};

U:=U {v};

end

end;

Якщо ввести два масиви, то можна порівняно просто організувати на кожному кроці алгоритму вибір ребра з найменшою вартістю, що з'єднує множини U і V\U. Масив CLOSEST[i] для кожної вершини i з множини V\U містить вершину з U, з якої він з'єднаний ребром мінімальної вартості (це ребро вибирається серед ребер, інцедентних вершині i, і які ведуть у множину U). Інший масив LOWCOST[i] зберігає значення вартості ребра (i, CLOSEST[i]).

На кожному кроці алгоритму проглядається масив LOWCOST, знаходимо мінімальне значення LOWCOST[k]. Вершина k безлічі V\U і з'єднана ребром з вершиною з множини U. Потім друкується ребро (k, CLOSEST[k]). Тому що вершина k приєднується до множини U, то внаслідок цього змінюються масиви LOWCOST і CLOSEST.

Після знаходження чергової вершини k остовного дерева LOWCOST[k] робимо рівним infinity (нескінченність), дуже великому числу, такому, щоб ця вершина надалі не розглядалася. Значення числа infinity повинне бути більше вартості будь-якого ребра графа.

Час виконання алгоритму Прима має порядок О(п2), оскільки виконується п - 1 ітерація зовнішнього циклу рядків (4) - (16), а кожна ітерація цього циклу вимагає часу порядку О(п) для виконання внутрішніх циклів у рядках (7) - (10) і (13) - (16). Алгоритм Крускала виконується за час порядку О(е log2e), де е — кількість ребер у даному графі.

Алгоритм Крускала

Побудова остовного дерева мінімальної вартості для графа G починається із графа P=(U, ), що складає тільки з n вершин графа G і не має ребер. Таким чином, кожна вершина є зв'язаним (із самим собою) компонентом (Ti ). Компоненти Ti є деревами, їхнє об'єднання дає початкове наближення мінімального остовного дерева.

При побудові зв'язкових, що поступово зростають компонентів по черзі перевіряються ребра з множини Е в порядку зростання їхньої вартості. Якщо чергове ребро зв'язує дві вершини з різних компонентів, тоді воно додається в граф P. Якщо це ребро зв'язує дві вершини з одного компонента, то воно відкидається, тому що його додавання у зв'язний компонент, що є вільним деревом, приведе до утворення циклу. Коли всі вершини графа G будуть належати одному компоненту (тобто буде включене ребро), побудова остовного дерева мінімальної вартості для цього графа закінчується.

Побудуємо алгоритм-схему для розв’язання поставленого завдання:

Введемо вектор Mark[u] міток вершин u U графа, що підтримує приналежність вершин компонентам зв’язності Еi, з яких формується реберний список остовного дерева. Початкові величини Mark[ui] установлюються рівними порядковим номерам відповідних вершин vi V. Далі значення Mark[ui] коректуються в міру злиття компонент Ei , зберігаючи відповідність приналежності їм вершин. Вихідний граф задається реберним списком Е, вихідне остовне дерево формується реберним списком Е0.

for ui U do Mark[ui] = i;

Sort(E); {Сортування списку ребер по їхнім вагам}

Е0:= ;

while | Е0 | <|U|-1 do begin

Знаходимо ребро(u,v) E з min вагою із що залишилися;

if Mark[u] <>Mark[v] then begin

Е0:= Е0 {(u, v)}; {Включити ребро в остовне дерево}

z: = Mark[v]; {Злиття }

for k U do

if Mark[k] = z then Mark[k] := Mark[u];

end;

E:= E\{(u, v)}; {Видалити ребро з min вагою зі списку}

end;