Студопедия

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

Разделы сайта

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






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). Как и в случае простых реа­лизаций сортировки, этот алгоритм может обеспечить квадратичную зависимость време­ни выполнения в худшем случае, однако мы можем рассчитывать на вероятностную га­рантию того, что время его выполнения в худшем случае не подойдет близко к указанному пределу. Кроме того, подобно простым реализациям сортировки, эта программа, по всей видимости, обеспечивает большее быстродействие, чем реализация на базе полного бинарного дерева, что обусловливается ее более коротким внутренним циклом.







© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.