Вы находитесь на странице: 1из 13

МИНОБРНАУКИ РОССИИ

САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ
ЭЛЕКТРОТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ
«ЛЭТИ» ИМ. В.И. УЛЬЯНОВА (ЛЕНИНА)
Кафедра информационной безопасности

ОТЧЕТ
по лабораторной работе №4
по дисциплине «Алгоритмы и структуры данных»
Тема: Построение минимального остовного дерева

Студент гр. 1363 Дао Н.Х.

Преподаватель Беляев А.В.

Санкт-Петербург
2022
Цель работы
Ознакомление с вариантами реализации алгоритмов на графах на примере
задачи построения минимального остовного дерева.
Теоретические сведения
Алгоритм Прима
Алгоритм начинается с выбора произвольной вершины. Она принимается
за часть построенного минимального остовного дерева.
Далее в цикле в каждой итерации рассматриваются только те ребра
исходного графа, одна из вершин которых строго принадлежит уже
построенной части, а другая строго не принадлежит (если второе условие не
проверять, то в графе возникнут циклы). Из списка всех ребер,
удовлетворяющих этому условию, выбирается ребро с наименьшим весом и
добавляется к построенной части.
Итерации повторяются до тех пор, пока все вершины не окажутся
включенными в остовное дерево.
Алгоритм Краскала
Алгоритм начинается с того, что каждая вершина исходного графа
помещается в свое множество (состоящее из одной вершины) – компоненту
связности.
Далее в цикле в каждой итерации из всех ребер, которые соединяют
разные компоненты связности, выбирается ребро с наименьшим весом, и с
помощью него две отдельные компоненты связности объединяются в одну.
Итерации повторяются до тех пор, пока количество компонент связности
не уменьшится до одной – она и будет представлять собой остовное дерево.
Оценка быстродействия алгоритмов
В случае «наивной» реализации (хранение информации о наличии и
стоимости ребер в двумерном массиве) асимптотика обоих алгоритмов – O(n2).
В случае применения более сложных структур для хранения сведений об
упорядоченном списке ребер – O(n·log2n).

2
Теоретическая часть
Дан взвешенный связный неориентированный граф «Куб» (Вариант 7):

1. Алгоритмом Прима.
1. 2.

3. 4.

5. 6.

3
7. 8.

9. 10.

11. 12.

13. 14.

15. 16.

4
ТАБЛ. 1 – ПРОЦЕСС СОЗДАНИЯ МИНИМАЛЬНОГО ОСТОВНОГО
ДЕРЕВА АЛГОРИТМОМ ПРИМА
2. Алгоритмом Краскала.
1. 2.

3. 4.

5.

6. 7.

5
8.

Табл. 1 – Процесс создания минимального остовного дерева алгоритмом Прима


3. Сравнить деревья, получившиеся алгоритмами 1 и 2, сравнить сумму
весов ребер.
Деревья, полученные алгоритмами Прима и Краскала, имеют
одинаковую форму и минимальную сумму весов ребер 78.

6
Практическая часть
Реализовать построение минимального остовного дерева для графа,
содержащего 15 вершин, по алгоритму Краскала.
Алгоритм генерации исходного графа, содержащего 15 вершин.

Рис. 1 – Список всех ребер с их весами

7
Алгоритма генерации минимального остовного дерева.

Рис. 2 – Итерации по выбранным ребрам к включению

8
Рис. 3 – Сумма весов включенных ребер

Выводы
Выполнив и изучив алгоритм Прима и алгоритм Крускала, мы
получаем возможность быстрого построения остовного дерева.
Анализируются длины ребер от каждой вершины фрагмента до оставшихся
невыбранных вершин. Выбирается минимальное ребро и присоединяется к
первоначальному фрагменту, и т. д. Процесс продолжается до тех пор, пока
в остовное дерево не будут включены все вершины исходного графа.

9
Исходный код
#include <iostream>
#include <ctime>
#include <map>
#include <vector>

using namespace std;

typedef struct Edge {


int weight, u, v;
};

//генерация исходного графа


void Graph(int** edge, int n) {
map <int, bool> vis;
int num[105] = { 0 };
for (int i = 0; i < 35; i++) {
int k;
do {
k = rand() % 105;
} while (vis.find(k) != vis.end());
vis[k] = true;
num[k] = 1 + rand() % 50;
}
int k = 0;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
edge[i][j] = num[k];
if (edge[i][i + 1] == 0)
edge[i][i + 1] = 200;
if (edge[i][j] != 0)
cout <<"Edge: " << i + 1 << "-" << j + 1 << " weight: " << edge[i][j] << endl;
k++;
}
}
cout << endl;
}
void SortEdge(vector <Edge> &E)
{
for (int i = 0; i < E.size(); i++)
{
for (int j = i + 1; j < E.size(); j++)
{
if (E[i].weight > E[j].weight)
{
Edge e;
e = E[i];
E[i] = E[j];
E[j] = e;
}
}
}
}
int checkV(int* Vertex, int n) {
for (int i = 0; i < n - 1; i++) {
if (Vertex[i] != Vertex[i + 1])
return 1;
}
return 0;
}
//Генерация минимального остовного дерева
void Kruskal(int** edge, int n) {
vector <Edge> E; //массив ребр
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (edge[i][j] != 0) {
Edge e;
e.weight = edge[i][j];
e.u = i;
e.v = j;
E.push_back(e);
}
}
}
SortEdge(E);
int* Vertex = new int[n]; //массив вершин
for (int i = 0; i < n; i++) {
Vertex[i] = i;
}
int** tree = new int* [n]; //минимальное остовное дерево
for (int i = 0; i < n; i++)
tree[i] = new int[n];
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)

11
tree[i][j] = 0;
//цикл по ребрам
for (int i = 0; i < E.size(); i++) {
cout << "Iteration number: " << i + 1 << endl;
cout << "Edge to include: " << E[i].u + 1 << "-" << E[i].v + 1 << "-weight: " << E[i].weight << endl;
cout << "Number of vertices in the first component: ";
for (int j = 0; j < n; j++) {
if (Vertex[j] == Vertex[E[i].u])
cout << j + 1 << " ";
}
cout << endl;
cout << "Number of vertices in the second component: ";
for (int j = 0; j < n; j++) {
if (Vertex[j] == Vertex[E[i].v])
cout << j + 1 << " ";
}
cout << endl << endl;
if (Vertex[E[i].u] != Vertex[E[i].v]) {
tree[E[i].u][E[i].v] = E[i].weight;
int v = Vertex[E[i].v];
for (int j = 0; j < n; j++) {
if (Vertex[j] == v)
Vertex[j] = Vertex[E[i].u];
}
if (checkV(Vertex, n) == 0) break;
}
}
cout << endl << "Minimum spanning tree: " << endl;
int minCost = 0;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (tree[i][j] != 0) {
minCost = minCost + tree[i][j];
cout << "Edge: " << i + 1 << "-" << j + 1 << " weight: " << tree[i][j] << endl;
}
}
}
cout << endl << "Minimum sum of weights = " << minCost << endl;
}
int main() {
int n = 15;
int** edge = new int* [n];
for (int i = 0; i < n; i++)

12
edge[i] = new int[n];
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
edge[i][j] = 0;
srand(time(NULL));
Graph(edge, n);
Kruskal(edge, n);
delete[] edge;
return 0;
}

13

Вам также может понравиться