
- •Задание на курсовую работу
- •Аннотация
- •Содержание
- •Введение
- •1. Система непересекающихся множеств
- •1.1 Описание структуры
- •1.2 Способы оптимизации
- •2. Хранение графа
- •Сортировка слиянием
- •Алгоритм краскала
- •4.1 Остовное дерево
- •4.2 Алгоритм Краскала
- •Заключение
- •Список использованных источников
- •Приложение а исходный код программы
Введение
Цель работы: реализовать алгоритм поиска минимального остова на основе алгоритма Краскала (Крускала). Продемонстрировать знания следующих вопросов:
- сортировка,
- обход графов,
- хранение графов,
- построение системы непересекающихся множеств.
Входные данные - любой текстовый файл, содержащий матрицу смежности графа в виде:
A B C
0 3 1
3 0 2
1 2 0
где первая строка содержит через пробел список всех рёбер, за которым следует матрица смежности. В матрице значение 0 стоит, если ребра между вершинами нет, положительный вес, если ребро идёт из вершины для этой строки.
Результат в виде отсортированных по имени пар и суммарный вес:
A C
B C
3
Максимальный размер входных данных: 50 вершин. Вершины могут быть заданы любой текстовой последовательностью без пробелов. Вес ребра ограничен интервалом от 1 до 1023 включительно.
В работе используется язык программирования Python с применением стандартных библиотек, а также структуры данных и алгоритмы, реализованные в рамках работы над лабораторными работами.
1. Система непересекающихся множеств
1.1 Описание структуры
Система непересекающихся множеств (англ. disjoint-set, или union–find data structure) — структура данных, которая позволяет администрировать множество элементов, разбитое на непересекающиеся подмножества. При этом каждому подмножеству назначается его представитель — элемент этого подмножества.
В структуре определены две операции:
union(x, y) — объединяет множества, содержащие x и y.
find(x) — возвращает представителя множества, в котором находится x.
Система непересекающихся множеств может быть реализована несколькими способами. В курсовой работе выбран способ реализации с помощью массивов.
Множество элементов хранится с помощью деревьев. Одно дерево соответствует одному множеству.
Заводится родительский массив, где для каждого элемента хранится ссылка на его предка. Корни деревьев ссылаются сами на себя и являются представителями этого множества.
Чтобы создать новый элемент, создаётся дерево с корнем в данной вершине, а её предком будет являться она сама.
Для объединения двух множеств сначала находятся лидеры этих множеств (то есть родители или корни). Если они совпали – множества уже объединены. Иначе – один из лидеров становится ребёнком второго.
Описанная версия алгоритма не является эффективной, она работает за O(n).
1.2 Способы оптимизации
Первый способ – объединение по рангу.
В реализации, описанной выше, выбор множества для объединения происходил случайно. Теперь для каждой вершины будем хранить её ранг.
Рангом в данном случае называем размеры поддеревьев вершины.
При объединении присоединение происходит к дереву с большим рангом.
При применении данного способа оптимизации мы ограничиваем высоту дерева до O(log n), а соответственно и асимптотику для операции нахождения корня.
Второй способ – сжатие пути.
При возвращении из рекурсивной функции будем записывать текущее значение родителя в узел. Таким образом, узел сразу же получит ссылку на своего самого высокого предка. Сжатие пути улучшает асимптотику до O(log n) в среднем случае.