Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Высокоцровневые методы информатики и првые методы информатики и программированияограммирования.doc
Скачиваний:
332
Добавлен:
01.05.2014
Размер:
14.7 Mб
Скачать

2.4.2 Сохранение основного свойства кучи

Процедура Heapify – важное средство работы с кучей. Её параметрами являются массив А и индекс i. Предполагается, что поддеревья с корнями Left(i) и Right(i) уже обладают основным свойством. Процедура переставля­ет элементы поддерева с вершиной i, после чего оно будет обладать основным свойством. Идея проста: если основное свойство не выполнено для вершины i, то её следует поменять с большим из её детей и т.д., пока элемент А[i] не «погрузится» до нужного места.

Рисунок 2.4 – Работа процедуры Heapify(A, 2) при heap-size[A] = 10

На рисунке 2.4 (а) отображено начальное состояние кучи. В вершине i = 2 основное свойство нарушено. Чтобы восстановить его, необходимо поменять А[2] и А[4]. После этого (б) основное свойство нарушается в вершине с индексом 4. Рекурсивный вызов процедуры Heapify(A, 4) восстанавливает основное свойство в вершине с индексом 4 путём перестановки А[4] А[9] (в). После этого основное свойство выполнено для всех вершин, так что процедура Heapify(A, 9) уже ничего не делает.

Листинг 2.4 – Процедура восстановления основного свойства кучи

Работа процедуры Heapify показана на рис. 2.4. В строках 3-7 в пере­менную largest помещается индекс наибольшего из элементов A[i], A[Left(i)] и A[Right(i)]. Если largest i, то элемент А[i] уже «погрузился» до нужного места, и работа процедуры закончена. Иначе процедура меняет местами А[i] и A[largest] (что обеспечивает выполнение основного свойства в вершине i, но, возможно, нарушает это свойство в вершине largest) и рекурсивно вызывает себя для вершины largest, чтобы исправить возможные нарушения.

Оценим время работы процедуры Heapify. На каждом шаге требуется произвести Θ(1) действий, не считая рекурсивного вызова. Пусть Т(п) – время работы для поддерева, содержащего n элементов. Если поддерево с корнем i состоит из n элементов, то поддеревья с корнями Left(i) и Right(i) содержат не более чем по 2/ 3 элементов каждое (наихудший случай – когда последний уровень в поддереве заполнен наполовину). Таким образом,

Эту же оценку можно получить так: на каждом шаге происходит спуск по дереву на один уровень, а высота дерева есть О(log n).

2.4.3 Построение кучи

Пусть дан массив A[1..n], который требуется превратить в кучу, переста­вив его элементы. Для этого можно использовать процедуру Heapify, приме­няя её по очереди ко всем вершинам, начиная с нижних. Поскольку вершины с номерами ,...,n являются листьями, поддеревья с этими вершинами удовлетворяют основному свойству. Для каждой из оставшихся вершин, в поряд­ке убывания индексов, мы применяем процедуру Heapify. Порядок обработки вершин гарантирует, что каждый раз условия вызова процедуры (выполнение основного свойства для поддеревьев) будут выполнены.

Листинг 2.5 – Процедура построения кучи

Ясно, что время работы процедуры Build-Heap не превышает O(nlog n). Действительно, процедура Heapify вызывается О(п) раз, а каждое её выпол­нение требует времени O(log n). Однако, эту оценку можно улучшить.

Итак, куча строится за линейное время, восстановление основного свойства кучи происходит за время, пропорциональное высоте дерева, т.е. log n, всего же сортируется

n - элементов, поэтому общее время есть O(nlog n).