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

Толстые кучи

Вспомогательные процедуры

  1. Процедура обновления прямого указателя i -го разряда счетчика нарушений аналогична процедуре {\rm UpdateForwardPointer}(i) для корневого счетчика. Необходимо лишь учесть, что счетчик нарушений — двоичный.
  2. Процедура корректировки списочной части i -го разряда счетчика нарушений при появлении в куче нового i -рангового нарушения — назовем ее {\rm InsertViolation}(i;{\rm pNode}) — вставляет новый нарушенный узел, обновляя, в зависимости от значения {\rm CountViolation}[i].{\rm Value}, либо первый ({\rm FirstViolation}), либо второй ({\rm SecondViolation}) указатель. Причем перед тем как вставлять в счетчик новое нарушение, необходимо проверить, не присутствует ли оно там.
  3. Процедура взаимной замены поддеревьев кучи с корнями в узлах p1 и p2 — назовем ее {\rm
InterChange}(p1,p2) — подразумевает, что ранги обмениваемых деревьев одинаковы.
  4. Также нам необходима функция {\rm SearchBrother}(p), которая возвращает указатель на брата того же ранга, что и передаваемый ей узел. Она проверяет ранги своего правого и левого братьев (если такие существуют) и возвращает указатель на брата того же ранга (он существует обязательно).
  5. Функция, которая связывает три толстых дерева ранга i в одно толстое дерево ранга i + 1, аналогична соответствующей функции для корневого счетчика.
  6. Функция, которая возвращает указатель на минимальный нарушенный узел ранга i среди элементов i -го разряда счетчика нарушений. Если i -й разряд счетчика нарушений пуст, то возвращается {\rm nil}.

Как и в случае корневого счетчика, все операции выполняются за константное время.

Свойство регулярности. Определим свойство регулярности для счетчика нарушений. Назовем состояние счетчика нарушений регулярным, если между любыми двумя цифрами, равными двум, существует цифра, отличная от единицы. Неправильный узел ранга i в дальнейшем будем называть i -ранговым нарушением.

Операция фиксации. Фиксация i -й цифры d_i = 2 соответствует либо преобразованию двух i -ранговых нарушений в одно (i + 1) -ранговое нарушение, либо устранению обоих i -ранговых нарушений. Проводить эту операцию предлагается следующим образом.

Упорядочиваем два i -ранговых нарушения так, чтобы они имели одного родителя (очевидно, что в общем случае i -ранговые нарушения могут иметь разных родителей). Сделать это предлагается заменой поддерева с корнем в нарушенном узле, чей родитель имеет меньший ключ, на поддерево с корнем в i -ранговом брате нарушаемого узла, чей родитель имеет больший ключ. Легко убедиться, что такая замена не приводит к созданию новых нарушений. Пусть узел y — общий родитель двух нарушаемых узлов после замены — принадлежит дереву F.

Разобьем дальнейшее рассмотрение на два случая:

  1. Ранг y равен i + 1. Пусть F_1 и F_2 — это толстые деревья ранга i с корнями в двух нарушаемых узлах, а дерево F^yтолстое дерево ранга i, полученное из поддерева с корнем в узле y удалением поддеревьев F^1 и F^2.
    • Если узел y не является корнем дерева F, то удаляем из дерева F поддерево F^y. Из трех толстых деревьев (F, F^1, F^2 ) ранга i образуем одно дерево ранга i + 1, чей корень z является узлом с наименьшим ключом среди корней деревьев F, F^1, F^2. Вставляем в дерево F вновь полученное толстое дерево с корнем в узле z вместо поддерева с корнем в узле y. Если узел z оказывается нарушенным, инкрементируем d_{i+1}. Значение i -го разряда делаем нулевым.
    • Если узел y — корень дерева F, то удаляем дерево F из кучи. Из трех толстых деревьев (F, F^1, F^2) ранга i образуем одно дерево ранга i, чей корень z является узлом с наименьшим ключом среди ключей корней деревьев F, F^1, F^2. Вставляем вновь полученное толстое дерево с корнем в узле z в кучу. Значение i -го разряда делаем нулевым.
  2. Если ранг y больше, чем i + 1, то, по условию регулярности счетчика нарушений, узел y должен иметь хотя бы одного сына w ранга i + 1, который не является (i +
1) -ранговым нарушением, и два i -ранговых сына w должны быть также ненарушенными. Тогда заменяем два нарушенных i -ранговых сына узла y на два хороших i -ранговых сына узла w. Тем самым мы свели задачу к случаю 1.

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

Инкрементирование i-го разряда счетчика нарушений ({\rm IncCount Violation(i,p)}). Используя описанную выше операцию фиксации, можно осуществить инкрементирование i -го разряда счетчика нарушений следующими операторами:

\formula{
{\rm FixCountViolation} (i);\\
{\rm FixCountViolation} ({\rm CountViolation} [i]\t{\^{}}.
{\rm ForwardPointer});\\
\mbox{}\q {\rm InsertViolation}(i, {\rm pNode});\\
{\rm CountViolation}[i].{\rm Value}:= {\rm CountViolation}[i].{\rm Value} +
1;\\
{\rm FixCountViolation} (i);\\
{\rm FixCountViolation}\ ({\rm CountViolation} [i]\t{\^{}}.
{\rm ForwardPointer});
}

Трудоемкость операции O(1).

Удаление нарушения из кучи. Заметим, что удаление нарушения из кучи подразумевает наличие в куче этого нарушения; пусть это нарушение ранга i. Тогда значение i -го разряда для счетчика нарушений не равно нулю. Следовательно, уменьшение этого значения на единицу не испортит регулярности и не потребует обновления каких-либо указателей. Необходимо лишь уменьшить на единицу значение переменной {\rm CountViolation} [i].{\rm Value} и обработать указатели {\rm FirstViolation} и {\rm SecondViolation}. Очевидно, что трудоемкость этой операции O(1).

Нахождение узла с минимальным значением ключа среди всех нарушений. Для реализации этой функции предлагается перебрать все нарушения до максимального ранга и найти среди них узел с минимальным весом. Трудоемкость данной операции O(\log n).

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

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

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