Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
AlgStr / Библиотека / Разные источники / Биномиальная куча (Вики).doc
Скачиваний:
40
Добавлен:
23.03.2015
Размер:
231.42 Кб
Скачать

[Править] Функциональность

Над кучей можно выполнять следующие операции:

  • Добавить элемент в кучу. Сложность O(logn)

  • Исключить максимальный элемент из кучи. Время работы O(logn)

  • Изменить значение любого элемента. Время работы O(logn)

На основе этих операций можно выполнять следующие действия:

  • Превратить неупорядоченный массив элементов в кучу. Сложность O(N)

  • Отсортировать массив путём превращения его в кучу, а кучи в отсортированный массив. Время работы O(nlogn)

Здесь N — количество элементов кучи. Пространственная сложность — O(1) для всех вышеперечисленных операций и действий.

Подробное описание и алгоритмы этих действий и процедуры Heapify, необходимой для их выполнения, приведены в следующем разделе.

[Править] Базовые процедуры

В этом разделе представлены основные процедуры для работы с кучей.

[Править] Восстановление свойств кучи

Если в куче изменяется один из элементов, то она может перестать удовлетворять свойству упорядоченности. Для восстановления этого свойства служит процедура Heapify. Она восстанавливает свойство кучи в дереве, у которого левое и правое поддеревья удовлетворяют ему. Эта процедура принимает на вход массив элементов Aи индексi. Она восстанавливает свойство упорядоченности во всём поддереве, корнем которого является элементA[i].

Если i-й элемент больше, чем его сыновья, всё поддерево уже является кучей, и делать ничего не надо. В противном случае меняем местамиi-й элемент с наибольшим из его сыновей, после чего выполняем Heapify для этого сына.

Процедура выполняется за время .

Heapify(A, i)

left ← 2i

right ← 2i+1

heap_size - количество элементов в куче

if leftA.heap_size и A[left] > A[i]

then largestleft

else largesti

if rightA.heap_size и A[right] > A[largest]

then largestright

if largesti

then Обменять A[i] ↔ A[largest]

Heapify(A,largest)

Можно повысить эффективность реализации, если избавиться от хвостовой рекурсии.

[Править] Построение кучи

Эта процедура предназначена для создания кучи из неупорядоченного массива входных данных.

Заметим, что если выполнить Heapify для всех элементов массива A, начиная с последнего и кончая первым, он станет кучей. В самом деле, легко доказать по индукции, что к моменту выполнения Heapify(A, i) все поддеревья, чьи корни имеют индекс больше i, кучи, и, следовательно, после выполнения Heapify(A, i) кучей будут все поддеревья, чьи корни имеют индекс, не меньший i.

Кроме того, Heapify(A,i) не делает ничего, если i>N/2 (при нумерации с первого элемента), где N — количество элементов массива. В самом деле, у таких элементов нет потомков, следовательно, соответствующие поддеревья уже являются кучами, так как содержат всего один элемент.

Таким образом, достаточно вызвать Heapify для всех элементов массива A, начиная (при нумерации с первого элемента) с [N/ 2]-го и кончая первым.

Время работы равно .

Build-Heap(A)

A.heap_sizeA.length

for i ← ⌊A.length/2⌋ downto 1

doHeapify(A,i)

[Править] Пирамидальная сортировка

Основная статья:Пирамидальная сортировка

Процедура Heapsort сортирует массив без привлечения дополнительной памяти за время .

Для понимания её работы можно представить, что мы обменяли первый элемент (то есть корень) с последним. Тогда последний элемент станет самым большим. Если после этого исключить последний элемент из кучи (то есть формально уменьшить её длину на 1), первые N-1 элементов будут удовлетворять условиям кучи все, за исключением, может быть, корня. Если вызвать Heapify, первые N-1 элементов станут кучей, а последний будет больше их всех. Повторяя эти действия N-1 раз, мы отсортируем массив.

Heapsort(A)

Build_Max_Heap(A)

for iA.length downto 1

do Обменять A[1] ↔ A[i]

A.heap_sizeA.heap_size-1

Heapify(A,1)