Будем использовать следующие процедуры, необходимые для реализации основных операций в структуре данных d-куча. Процедура Swap(i, j) меняет местами ключи вершин i и j. Например, для d-кучи (d = 2), представленной массивом

i01234567
dHeap[i]5674811129

применим процедуру swap(4, 6)

Пример кучи перед перестановкой swap(4, 6) и после проведенной перестановки.

Псевдокод процедуры Swap(i, j):

procedure Swap(i, j);
begin
k := key[i];
key[i] := key[j];
key[j] := k;
end;

Трудоемкость процедуры Swap(i, j) есть O(1).

В процессе работы над d-кучей часто требуется менять значения ключей, переставлять элементы. При этом может временно нарушаться основное свойство кучи (инвариант 1).

i-ой вершины key[i] и и пусть j = Pred[i]. Тогда могут возникнуть два случая:

Эту задачу выполняет процедура SiftUp(i):

procedure SiftUp(i);
begin
while (i <> root) and (key[i] < key[Pred[i]]) do
{
Swap(i, Pred[i]);
i := Pred[i];
}
end;

Процедура SiftUp(i) имеет трудоемкость O(logdn), т.к. после каждой итерации цикла уменьшается глубина узла i, а согласно свойству d-дерева, его начальная глубина – O(logdn).

Предположим далее, что мы увеличили ключ некоторой вершины i. Возможны два случая:

procedure SiftDown(i);
begin
while (i <> leaf) and (key[i] > key[minchild(i)]) do
{
Swap(i, minchild(i));
i := minchild(i);
}

Процедура SiftDown(i) требует O(d logdn) операций, т.к. на поиск листа затрачивается O(logdn) операций, а вычисление minchild(i) требует O(d) операций.

Покажем, что для d-кучи основные операции могут быть реализованы с помощью процедур SiftUp(i), SiftDown(i), Swap(i, j).

Нахождение вершины с минимальным ключом find_min(i, dHeap).

Эта операция находит вершину с минимальным ключом. Она находится в корне, а поскольку d-куча представлена в виде массива, то минимальный элемент находится в позиции с индексом 0. Для нахождения вершины с минимальным ключевым значением необходимо выполнить O(1) операций в наихудшем случае.

Вставка элемента в d-кучу insert(i, dHeap).

Эта операция осуществляет вставку новой вершины i в d-кучу путем добавления новой вершины в конец массива dHeap[i], i = 0, ..., last, где last – индекс последнего элемента перед вставкой новой вершины i в d-кучу, т.е. dHeap[last] := key[i], после чего last надо увеличить на 1. Поскольку добавление новой вершины может нарушить инвариант 1, то восстанавливаем его с помощью процедуры SiftUp(i).

procedure insert(i, dHeap)
begin
dHeap[last] := key[i];
last := last + 1;
SiftUp(last);
end;

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

Удаление минимального элемента из d-кучи. Операция delete_min(i, dHeap).

Удаление будем производить следующим образом: меняем первый элемент d-кучи (минимальный элемент) с последним и уменьшаем размерность d-кучи на 1. Такая замена может нарушить инвариант 1. Для восстановления инварианта 1, начиная с корневой вершины двигаемся по единственному пути до некоторой вершины k, для которой инвариант 1 выполнен. Это производится с помощью процедуры SiftDown(i), i = root. Псевдокод процедуры удаления минимального элемента из d-кучи:

procedure delete_min(i, dHeap)
begin
Swap(root, last);
last := last - 1;
SiftDown(root);
end;

Трудоемкость этой процедуры O(logdn).

Наряду с основными операциями в d-куче часто рассматриваются операции:

Hosted by uCoz