Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Data Structures and Algorithms in C++ 2e (На ру...docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
2.37 Mб
Скачать

Глава 8. Кучи и приоритетные очереди

Затем, в Кодовом Фрагменте 8.16, мы представляем внедрение вставки op-eration. Как обрисовано в общих чертах в предыдущей секции, это работает, добавляя новый элемент к последнему положению дерева, и затем это выполняет-кучу, пузырящуюся, неоднократно обменивая этот элемент с его родителем, пока у его родителя нет меньшего значения ключа.

шаблон <typename E, typename C> //вставляют элемент

недействительный HeapPriorityQueue <E, C>:: вставка (константа E& e)

T.addLast (e); //добавляют e к куче

Положение v = T.last (); //положение e

в то время как (! T.isRoot(v)) //-куча bubbl i ng

Положение u = T.parent(v);

если (! острова (*v, *u)) разрыв; //, если v в заказе, мы сделаны T.swap (v, u); //.. .else обмениваются с родительским v = u;

\ Кодовый Фрагмент 8.16: внедрение вставки функции.

Наконец, давайте рассмотрим removeMin операцию. Если у дерева есть только один узел,

тогда мы просто удаляем его. Иначе, мы обмениваем элемент корня с последним элементом дерева и удаляем последний элемент. Мы тогда применяем вниз-кучу, пузырящуюся к корню. Разрешение u обозначает текущий узел, это включает определение маленького ребенка u, который сохранен в v. Если ключ ребенка меньше, чем u's, мы обмениваем содержание u с этим ребенком. Кодекс представлен в Кодовом Фрагменте 8.17.

шаблон <typename E, typename C> //удаляют минимум

недействительный HeapPriorityQueue <E, C>:: removeMin ()

если (размер () == 1) //o nl y o ne no de?

T.removeLast (); //.. .remove это

еще

Положение u = T.root (); //внедряют положение

T.swap (u, T.last ()); //обменивают в последний раз с корнем T.removeLast (); //.. .and удаляют в последний раз

в то время как (T.hasLeft (u)) //пузырение вниз-кучи

Положение v = T.left (u);

если (T.hasRight (u) && isLess (* (T.right (u)), *v))

v = T.right (u); //v - маленький ребенок u

если (острова (*v, *u))

T.swap (u, v);

u = v;

еще разрыв;

//u не в порядке?//.. обмен .then

//еще мы сделаны

Кодовый Фрагмент 8.17: основанное на куче внедрение приоритетной очереди.

8.3. Кучи 351

8.3.5 Вид кучи

Поскольку мы ранее наблюдали, понимая, что приоритетная очередь с кучей имеет

преимущество, которым все функции в приоритетной очереди ADT управляют в логарифмическое время или лучше. Следовательно, эта реализация подходит для заявлений, где быстрая продолжительность разыскивается все приоритетные функции очереди. Поэтому, давайте снова рассмотрим схему сортировки PriorityQueueSort от Раздела 8.1.5, который использует приоритетную очередь P, чтобы сортировать список L.

Во время Фазы 1 операция по вставке i-th (£ £1 in) берет O (1 +, регистрируются i), время,

так как у кучи есть я записи после того, как операция будет выполнена. Аналогично, во время

Фаза 2, операция j-th removeMin (1£ j£ n) бежит вовремя O (1+log (n-j +1),

так как у кучи есть n- j + 1 записи в то время, когда операция выполнена. Таким образом,

каждая фаза берет O (n, регистрируют n), время, таким образом, вся приоритетная очередь, сортирующая пробеги алгоритма

в O (n регистрируют n), время, когда мы используем кучу, чтобы осуществить приоритетную очередь. Этот алгоритм сортировки более известен как вид кучи, и его работа получена в итоге в следующем суждении.

Суждение 8.6: алгоритм вида кучи сортирует список L n элементов в O (n, регистрируют n),

время, принимая два элемента L может быть сравнено в O (1) время.

Давайте подчеркнем, что O (n регистрируют n) продолжительность вида кучи значительно лучше

чем O (n2) продолжительность вида выбора и вида вставки (Раздел 8.2.2) и по существу самое лучшее для любого алгоритма сортировки.

Осуществление оперативного вида кучи

Если список L, который будет сортирован, осуществлен посредством множества, мы можем ускорить кучу -

вид и уменьшает свое космическое требование постоянным множителем, используя часть самого списка L, чтобы сохранить кучу, таким образом избегая использования внешней структуры данных кучи. Эта работа достигнута, изменив алгоритм следующим образом:

1. Мы используем обратный компаратор, который соответствует куче где самое большое

элемент наверху. В любое время во время выполнения алгоритма, нас

используйте левую часть L, до определенного разряда i- 1, чтобы сохранить элементы в

куча и правильная часть L, от разряда i к n- 1, чтобы сохранить элементы в списке. Таким образом, первое я элементы L (в разрядах 0..., i-1), обеспечивают вектор

представление кучи (с измененными числами уровня, начинающимися в 0 вместо этого

из 1), то есть, элемент в разряде k больше, чем или равен его «детям» в разрядах 2k + 1 и 2k + 2.

2. В первой фазе алгоритма мы начинаем с пустой кучи и двигаемся

граница между кучей и списком слева направо, один шаг за один раз.

В шаге i (я = 1..., n), мы расширяем кучу, добавляя элемент в i-1 разряда

и выполните пузырение-кучи.

352