Министерство образования РФ

Нижегородский государственный университет имени

Факультет ВМК

Лабораторная работа № 1.2

«Нахождение кратчайших путей в графе»

Выполнил:

группа № 86М2,

Проверил:

Н. Новгород

2008 г.

Оглавление

Оглавление. 2

Описание алгоритмов. 3

Описание структур данных. 3

Алгоритм Дейкстры, реализованный на основе Д-кучи. 3

Обоснование теоретической оценки временной сложности алгоритмов. 5

Алгоритм Дейкстры, реализованный на основе Д-кучи. 5

Описание реализующих алгоритмы программ.. 6

Проведенные эксперименты.. 7

Сравнение алгоритмов. 15

Выводы.. 16

Описание алгоритмов

Описание структур данных

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

В алгоритмах используется также приоритетная очередь на основе Д-кучи. Д-куча представлена как три массива: массив имен вершин, массив ключей вершин (где ключ вершины – это оценка кратчайшего расстояния от исходной вершины до данной) и массив индексов вершин (то есть номеров вершин в приоритетной очереди). Приоритетная очередь на основе Д-кучи строится так: Д-куча представляется как корневое дерево, где корень находится на наивысшем уровне. Корнем является вершина с наименьшим ключом. Каждая вершина (не лист), кроме, возможно, одной имеют ровно Д потомков. Ключ каждого потомка вершины не меньше ключа самой вершины. Таким образом, высота Д-кучи равна [logdn]. С Д-кучей осуществляются следующие операции: всплытие вершины (вершина с ключом, меньшим, чем у родителя, поднимается наверх, пока не займет соответствующее ее ключу положение), погружение вершины (вершина с ключом, большим, чем у потомка, опускается вниз, пока не займет соответствующее ее ключу положение), изъятие минимума (выбор и удаление вершины с наименьшим ключом), образование приоритетной очереди. Для каждой вершины Д-кучи можно определить ее первого, последнего и минимального потомка и родителя.

НЕ нашли? Не то? Что вы ищете?

В данной лабораторной работе рассматриваются два алгоритма: алгоритм Дейкстры, основанный на использовании 3-кучи и алгоритм Дейкстры, основанный на использовании 4-кучи. Оба алгоритма возвращают два массива значений: массив расстояний от исходной вершины до всех остальных и массив «отцов» (последних вершин на пути от исходной). Т. к. алгоритмы различаются только значением числа Д, а в остальном они одинаковы, рассмотрим общую схему их работы.

Алгоритм Дейкстры, реализованный на основе Д-кучи

В данном алгоритме сначала происходит создание Д-кучи, а затем инициализация массивов, хранящих Д-кучу и предварительная инициализация возвращаемых массивов. Массив «отцов» инициализируется нулями, массивы расстояний и ключей в Д-куче инициализируются неким «большим» значением (это значение должно быть больше длины любого пути в графе), массивы имен и индексов в Д-куче инициализируются последовательно натуральными числами от 1 до количества вершин в графе. Ключ исходной вершины устанавливается как ноль. Далее на основе Д-кучи организуется приоритетная очередь.

Пока приоритетная очередь не исчерпана, выполняются следующие действия: извлекается минимум, расстояние до данной вершины устанавливается равным ее ключу, далее выполняется просмотр всей окрестности этой вершины. В ходе просмотра окрестности, пока не достигнут конец окрестности, для каждой вершины выполняются следующие действия: сравнивается ключ текущей вершины с суммой расстояния от исходной вершины до вершины-родителя и веса ребра из вершины-родителя в текущую вершину. Если ключ больше, то он устанавливается равным данной сумме, затем происходит всплытие текущей вершины в приоритетной очереди, «отцом» текущей вершины устанавливается вершина-родитель.

Обоснование теоретической оценки временной сложности алгоритмов

Алгоритм Дейкстры, реализованный на основе Д-кучи

Теорема:

Временная сложность алгоритма Дейкстры, реализованного на основе Д-кучи (Д является константой, не меньшей 2), оценивается сверху величиной O((d*n+m)×logdn), где n - число вершин, m - число ребер.

Доказательство:

Рассмотрим сначала временную сложность алгоритмов, производимых с Д-кучей. Очевидно, что при реализации Д-кучи в виде трех массивов, временная сложность таких операций, как определить первого, последнего потомков и отца вершины, будет О(1). Определение минимального потомка осуществляется за время О(d), так как происходит в общем случае не более d сравнений. Всплытие осуществляется за время О(logdn), так как происходит не более чем logdn сравнений и обменов. Погружение осуществляется за время О(dlogdn), так как происходит не более logdn обменов, при каждом из которых выполняется ровно d сравнений. Операция «изъятие минимума» сводится к одному погружению, соответственно и временная сложность ее такая же. Организация приоритетной очереди на основе Д-кучи осуществляется за время О(n). Докажем это. Заметим, что трудоемкость погружения с высоты h равна O(h), а количество узлов высоты h не превосходит целой части от n/dh +1(это несложно доказать по индукции: на наивысшем уровне только один узел, на каждом последующем не более чем в d раз больше; под высотой узла понимается расстояние от него до наиболее далекого потомка). Осталось оценить сумму

где H=[logdn]+1, и убедиться, что полученная сумма есть O(n).

==(воспользуемся формулой =)==О(n).

Теперь доказательство оценки временной сложности алгоритма: в ходе этого алгоритма выполняются следующие действия: инициализация пяти массивов длиной n (время пропорционально 5n), организация приоритетной очереди (время пропорционально n), n изъятий минимума (время пропорционально dlogdn) и не более m всплытий (время пропорционально logdn). «Изъятий минимума» ровно n, так как просматривается вся очередь, и всплытий не более m, так как вершина может «опускаться» не с каждым ребром. Итого затрачивается времени 6n+ndlogdn+mlogdn, то есть О((d*n+m)* logdn). Доказательство теоремы закончено.

Описание реализующих алгоритмы программ

Структуры данных «граф», «окрестность», «Д-куча» реализованы в данной программе как классы, структура данных «вершина графа» реализована как структура. Сами структуры подробно описаны в главе «Описание алгоритмов». В класс «Граф» добавлены также два числовых поля – минимальная и максимальная границы веса ребра. Процедура, реализующая алгоритм, содержатся в классе «Граф». Таким образом, временные структуры данных, которые используются только в данных алгоритмах (Д-куча и массив меток), создаются и освобождаются непосредственно в ходе соответствующих процедур. На это тратится лишнее время, не занятое полезными вычислениями.

Программы написаны на языке С++ в среде программирования Borland C++ Builder 5.0. Каждая структура данных хранится в отдельном модуле, кроме того, для каждой программы существует модуль, описывающий основную форму и связанные с ней действия.

Интерфейс программ прост и интуитивно понятен. Более подробную информацию о программах и работе с ними можно узнать в прилагающихся к ним инструкциях.

Проведенные эксперименты

В данной лабораторной работе проведены семь серий экспериментов. В каждой серии один из параметров изменяется от одного определенного значения до другого с определенным шагом. Результаты работы алгоритмов в ходе обработки каждой серии представлены на соответствующих графиках. На данных графиках по оси Х отложены значения изменяющегося параметра, а по оси Y время в секундах. Для наглядности графики работы обоих алгоритмов нарисованы в одной системе координат, при этом красная ломаная соответствует алгоритму Дейкстры, использующему 3-кучу, синяя – алгоритму Дейкстры, использующему 4-кучу. В обозначениях серии используются следующие условные обозначения: n – число вершин графа, m – число ребер графа, r – верхняя граница веса ребра, q – нижняя граница веса ребра.

Итак, рассмотрим проведенные эксперименты:

1) n = 1,...,1001 с шагом 10, q = 1, r = 106, m = n2/10

2) n = 1,...,1001 с шагом 10, q = 1, r = 106, m = n2

3) n = 101,...,3001 с шагом 30, q = 1, r = 106, m = 100*n

4) n = 101,...,3001 с шагом 30, q = 1, r = 106, m = 1000*n

5) n = 3001, m = 0,...,900’000 с шагом 10’000, q = 1, r = 106

6) n = 1000, q = 1, r = 1,...,200 с шагом 1, m = n2

7) n = 500, q = 1, r = 1,...,200 с шагом 1, m = 100*n

Сравнение алгоритмов

Как мы можем видеть на основании графиков, алгоритм Дейкстры, использующий 4-кучу, работает быстрее, чем алгоритм, использующий 3-кучу, во всех сериях в подавляющем большинстве случаев (за исключением некоторых отдельных частных экспериментов).

Следует отметить тот факт, что, согласно экспериментам, ширина диапазон веса ребра не влияет на время работы алгоритма (независимо от количества вершин и ребер).

Полученные графики являются достаточно гладкими, однако при этом в них иногда встречаются неожиданные относительно узкие всплески («пики»), которые, скорее всего, являются следствием «помех» от фоновых процессов операционной системы.

Выводы

Из приведенного сравнения алгоритмов можно сделать следующие выводы:

1.  алгоритм Дейкстры, использующий 4-кучи в большинстве случаев быстрее, чем алгоритм, использующий 3-кучу;

2.  т. к. полученная нами оценка является верхней, но не асимптотической, и получение асимптотической оценки не представляется возможным, вывод о соответствии теории и практики сделаем на основании следующих рассуждений:

·  каждый график соотнесем с некоторой стандартной функцией имеющей график похожего вида; несложно заметить, что графики 1 и 2 напоминают параболу (Q(n2)), 3 и 4 – линейную функцию (Q(n)), 5 – линейную функцию (Q(m)), 6 и 7 – константу (Q(1));

·  в случаях 1 и 2 m=c*n2; таким образом, верхнюю оценку можно переписать в виде O(n2*logdn), причем данная функция асимптотически больше, чем функция Q(n2);

·  в случаях 3 и 4 m=c*n; таким образом, верхнюю оценку можно переписать в виде O(n*logdn), причем данная функция асимптотически больше, чем функция Q(n);

·  в случае 5 m=c*n; таким образом, верхнюю оценку можно переписать в виде O(m) (т. к. параметром серии экспериментов является число ребер), причем данная функция асимптотически не меньшее функции Q(m);

·  в случаях 6 и 7 графики (с учетом незначительных колебаний) являются константными, что говорит о том, что время работы алгоритмов не зависит от ширины диапазона весов ребер, а также от значений верхней и нижней границы этого диапазона.

На основании всего вышеизложенного мы видим, что практические результаты во всех случаях асимптотически не превосходят полученную нами верхнюю оценку. Таким образом, можно сделать вывод о том, что практика соответствует полученным теоретическим результатам.