Студопедия

Главная страница Случайная страница

КАТЕГОРИИ:

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Class MST






{ const Graph & G;

vector< EdgePtr> a, mst;

UF uf; public:

MST(Graph & G): G(G), uf(G.V()), mst(G.V())

{ int V = G.V(), E = G.E();

a = edges< Graph, Edge, EdgePtr> (G); sort< EdgePtr> (a, 0, E-l);


РИСУНОК 20.13. АЛГОРИТМ КРУСКАЛА, ОБЕСПЕЧИВАЮЩИЙ ПОСТРОЕНИЕ ДЕРЕВА MST

Эта последовательность показывает 1/4, 1/2, 3/4 всех ребер и все ребра дерева MST no мере его роста.


Глава 20, Минимальные остовные деревья



for (int i = 0, к =s 1; i < E & & к < V; i++) if (! uf.find(a[i]-> v, a[i]-> w)) { uf.unite(a[i]-> v, a[i]-> w);

mst[k++] = a[i]; } } };

Свойство 20.9. Алгоритм Крускала вычисляет дерево MST графа за время, пропорциональ­ное Е lgE.

Доказательство: Это свойство является следствием более общего факта, устанавлива­ющего, что время выполнения программы 20.8 пропорционально затратам на сорти­ровку Е чисел плюс стоимость Е операций поиска (find) и V- 1 операций объединения (union). Если мы используем стандартные реализации АТД, такие как сортировка сли­янием и взвешенный алгоритм поиска-объединения с делением пополам, то основные затраты приходятся на сортировку. ■

Мы проведем сравнение производительности алгоритмов Крускала и Прима в разде­ле 20.6. А пока обратите внимание на то обстоятельство, что время выполнения, пропор­циональное E lgE, не обязательно хуже, чем E lgV, поскольку Е, самое большее, может достигать значения V2, следовательно, lgE нe превосходит 21gV Различие в производи­тельности на конкретных графах обусловливаются особенностями реализации и зависят от того, приближается ли фактическое время выполнения к этим граничным значениям, соответствующим худшему случаю.

На практике мы можем воспользоваться быстрой сортировкой или быстрой систем­ной сортировкой (в основу которой, скорее всего, будет положена быстрая сортировка). И хотя следствием такого подхода может быть непривлекательная (по крайней мере, в теории) квадратичная зависимость времени выполнения сортировки в худшем случае, тем не менее, она, по-видимому, может дать максимально возможное быстродействие рас­сматриваемого алгоритма. В самом деле, с другой стороны, мы можем воспользоваться поразрядной сортировкой, чтобы выполнить упорядочение ребер за линейное время (при определенных ограничениях на веса ребер), благодаря чему затраты на выполнение Е операций find будут составлять основную часть всех затрат, и внести изменения в форму­лировку свойства 20.9, в результате чего это свойство будет утверждать, что при сохра­нении прежних требований к весам ребер время выполнения алгоритма Крускала не вы­ходит за пределы постоянного коэффициента в выражении E lgE (см. главу 2). Напомним, что функция l g*E есть число итераций двоичной логарифмической функции, прежде чем результат примет значение меньше единицы; ее значение меньше 5, если Е меньше 265536. Другими словами, такая корректировка делает алгоритм Крускала в дей­ствительности линейным в большинстве практических ситуаций.

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



Часть 5. Алгоритмы на графах


с приоритетами, реализация которой применяет операцию construct (построить), выпол­няющуюся за линейное время, и операцию remove the minimum (удалить минимальное реб­ро) за логарифмическое время.

Например, мы можем достичь таких рабочих характеристик в рамках стандартной ре­ализации полного бинарного дерева, используя для этой цели восходящую конструкцию (см. раздел 9.4). В частности, мы вносим в программу 20.8 следующие изменения: снача­ла мы вызываем процедуру sort с целью вызова функции pq.constmct() с тем, чтобы по­строить полное бинарное дерево за время, пропорциональное Е. Затем мы вносим изме­нения во внутренний цикл, суть которых состоит в отборе из очереди с приоритетами самых коротких ребер, т.е. е = pq.delmin(), и замене всех обращений к a[i] на обраще­ния к е.

Свойство 20.10. Версия алгоритма Крускала, в основу которой положена очередь с при­оритетами, вычисляет дерево MST графа за время, пропорциональное Е + X lg V, где X есть число ребер графа, не превосходящих по длине самое длинное ребро в дереве MST.

Доказательство: Обратимся к предыдущему обсуждению, которое показывает, что зат­раты на вычисление рассматриваемого алгоритма суть затраты на построение очере­ди размера Е плюс стоимость выполнения X операций удалить ребро минимальной дли­ны (delete the minimum), X операций поиска (find) и V-1 операций объединения (union). Обратите внимание, что основная доля затрат приходится на построение очереди с приоритетами (и рассматриваемый алгоритм линеен во времени), пока X больше E/lgV.

Мы можем воспользоваться той же идеей для получения аналогичных выгод от реа­лизации рассматриваемого алгоритма на основе быстрой сортировки. Рассмотрим, что случится, если мы воспользуемся прямой рекурсивной быстрой сортировкой, по условиям которой мы проводим разбиение на элементе i, затем проводим рекурсивную сортиров­ку подфайла, расположенного слева от i, и подфайла справа от i. Мы учитываем тот факт, что в силу особенностей построения алгоритма, первые i элементов расположены в по­рядке, установленном сортировкой после завершения первого рекурсивного вызова (см. программу 9.2). Этот очевидный факт позволяет немедленно получить быстродействующую реализацию алгоритма Крускала: если мы поместим проверку, порождает ли ребро a[i] цикл между рекурсивными вызовами, та получаем алгоритм, который, в соответствие с конструкцией, выполняет проверку первых i ребер в порядке сортировки по завершении первого рекурсивного вызова! Если мы включим проверку на повторное выполнение, после того как мы уже выявили V— 1 ребер дерева MST, то мы имеем в своем распоря­жении алгоритм, который сортирует столько ребер, сколько их необходимо для вычис­ления дерева MST, плюс несколько дополнительных стадий разбиения, использующих элементы с большими значениями (см. упражнение 20.57). Как и в случае простых реа­лизаций сортировки, этот алгоритм может обеспечить квадратичную зависимость време­ни выполнения в худшем случае, однако мы можем рассчитывать на вероятностную га­рантию того, что время его выполнения в худшем случае не подойдет близко к указанному пределу. Кроме того, подобно простым реализациям сортировки, эта программа, по всей видимости, обеспечивает большее быстродействие, чем реализация на базе полного бинарного дерева, что обусловливается ее более коротким внутренним циклом.



Поделиться с друзьями:

mylektsii.su - Мои Лекции - 2015-2024 год. (0.006 сек.)Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав Пожаловаться на материал