Опубликован: 26.09.2006 | Уровень: специалист | Доступ: платный
Лекция 9:

Толстые кучи

Основные операции

Операция make-heap заключается в инициализации счетчиков. Трудоемкость O(1).

Операция FindMin возвращает указатель на минимальный элемент. Трудоемкость O(1).

Операция Insert(key). Чтобы выполнить эту операцию, делаем новый элемент отдельным деревом и выполняем процедуру вставки нового элемента ранга 0 в корневой счетчик. После этого, если необходимо, корректируем значение указателя на минимальный элемент.

Операция уменьшения ключа DecreaseKey. Чтобы выполнить эту операцию, поступим следующим образом. Пусть x — узел, на который указывает указатель p. Вычитаем \Dl из ключа узла x. Если новый ключ x меньше минимального ключа кучи H, обмениваем ключ элемента p с ключом минимального элемента. Новых нарушений операция не создаст. Пусть rранг x. Если x — нарушаемый узел, добавляем x как новое r -ранговое нарушение инкрементированием r -й цифры d_r счетчика нарушений. Трудоемкость O(1).

Операция DeleteMin выполняется следующим образом. Удаляем поддерево с корнем в минимальном узле из леса. Минимальность этого элемента гарантирует нам, что среди его детей нарушений порядка кучи не было. То есть нет необходимости работать со счетчиком нарушений. Затем вставляем в кучу все деревья с корнями, расположенными в детях удаляемого узла. Очевидно, что новый минимальный ключ — либо в корне дерева леса, либо в нарушенном узле. Выполняем поиск нового минимального элемента среди корней деревьев и нарушенных узлов.

Если минимальный элемент оказался в нарушенном узле, то обмениваем его с элементом, хранимым в корне этого дерева, корректируя корневой счетчик, если это необходимо. После замены новый минимум — в корне дерева леса. Этот корень будет новым минимальным узлом. Трудоемкость операции равна O(\log n).

Операция удаления элемента. Выполняется с помощью {\rm DecreaseKey} и затем {\rm DeleteMin}. Трудоемкость операции O(\log n).

Операция Meld(h1, h2). Выполняется следующим образом. Первый шаг — фиксируются все нарушения в куче с меньшим максимальным рангом (разрывая связь произвольно). Не уменьшая общности, считаем, что эта кучаh2. Пройти по счетчику нарушений h2 от младшей цифры к старшей, пропуская цифры со значением 0. Для i -й цифры d_i \ne 0 делаем операцию фиксирования на каждой цифре, показываемой прямым указателем d_i, если эта цифра имеет значение 2. Затем, если d_i = 2, фиксируем d_i. Если d_i = 1, преобразуем это i -ранговое нарушение в (i +
1) -ранговое нарушение, как при фиксировании, используя i -рангового брата нарушенного узла вместо (несуществующего) другого i -рангового нарушения.

Как только h2 не будет содержать каких-либо нарушений, нужно вставить корни из корневого счетчика h2 в корневой счетчик h1 инкрементированием соответствующих цифр. Если минимальный узел h2 содержит меньший ключ, чем минимальный узел h1, следует установить новым минимальным узлом h1 минимальный узел h2. Затем нужно вернуть модифицированную кучу h1 в качестве результата {\rm
Meld}. Трудоемкость операции равна O(\log n).

Операция DeleteViolation. Для освобождения кучи от нарушений достаточно выполнить операторы

\formula{
\t for\ i:= 0\ \t{to}\ h2\t{\^{}}.{\rm
MaxRank}\ \t do\\
\t if\ ({\rm CountViolation}[i].{\rm
Value} = 2)\
\t then\ {\rm FixCountViolation}(i);\\
\t for\ i:= 0\ \t{to}\ h2\t{\^{}}.{\rm
MaxRank}\ \t do\
\t if\ ({\rm CountViolation}[i].{\rm
Value} = 1)\ \t then \\
\{{\rm IncCountViolation}(i, {\rm SearchBrother}
({\rm CountViolation}[i].{\\rm FirstViolation}));\\
{\rm FixCountViolation}(i)\};
}

Основываясь на описанной выше реализации толстой кучи, получаем следующий результат. В толстых кучах операции {\rm FindMin}, {\rm
Insert} и {\rm DecreaseKey} выполняются за время O(1), а {\rm Delete}, {\rm DeleteMin} и {\rm Meld} — за время O(\log n).

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

Г.Бродал описывает кучевидную структуру, которая теоретически лучше, чем толстые кучи, так как их временная оценка для {\rm Meld}O(1) в худшем случае. Структура Бродала, однако, намного сложнее толстых куч.

Антон Сиротинкин
Антон Сиротинкин

на стр 6, лекции 3, Очевидно "Ck <= модуль(Gk(е))*b(k+1)" (1) - , подскажите что значит "модуль" и почему это очевидно...
 

Дмитрий Степаненко
Дмитрий Степаненко
Россия
Эдуард Санин
Эдуард Санин
Украина, Харьков, ХАИ