Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Шаповалов / lex_5.doc
Скачиваний:
65
Добавлен:
19.04.2015
Размер:
657.41 Кб
Скачать

3.Пиромидальная сортировка (сортировка с помощью кучи).

Рассмотрим еще один алгоритм сортировки, а именно - пирами­дальную сортировку. Время работы этого алгоритма, как и время работы алгорит­ма сортировки слиянием (и в отличие от времени работы алгоритма сортировки вставкой), равно O(nlgn). Как и сортировка методом вставок, и в отличие от сортировки слиянием, пирамидальная сортировка выполняется без привлечения дополнительной памяти: в любой момент времени требуется память для хранения вне массива только некоторого постоянного количества элементов. Таким образом, в пирамидальной сортировке сочетаются лучшие особенности двух рассмотрен­ных ранее алгоритмов сортировки.

Пирамида (binaryheap) - это структура данных, представляющая собой объ­ект-массив, который можно рассматривать как почти полное бинарное дерево (см. тему № 2). Каждый узел этого дерева соот­ветствует определенному элементу массива. На всех уровнях, кроме, может быть, последнего, дерево полностью заполнено (заполненный уровень — это такой, ко­торый содержит максимально возможное количество узлов). Последний уровень заполняется слева направо до тех пор, пока в массиве не закончатся элементы. Представляющий пирамиду массивА является объектом с двумя атрибутами:length [A], т.е. количество элементов массива, иheap_size [A], т.е. количество эле­ментов пирамиды, содержащихся в массивеА. Другими словами, несмотря на то, что в массивеА [1..length [А]] все элементы могут быть корректными чис­лами, ни один из элементов, следующих после элементаА[heap__size[A]], гдеheap_size [А] length [А], не является элементом пирамиды. В корне дерева на­ходится элементА [1], а дальше оно строится по следующему принципу: если какому-то узлу соответствует индексi, то индекс его родительского узла вычис­ляется с помощью представленной ниже процедурыParent(i), индекс левого дочернего узла - с помощью процедурыLEFT(i), а индекс правого дочернего узла — с помощью процедурыRight(i):

Рис. 5.3. Построение пирамиды.

Принцип работы метода.

Алгоритм основан на том, что сортируемому массиву может быть поставлено в соответствие двоичное дерево, каждый узел которого соответствует одному элементу массива с некоторым номером kи этот узел содержит ссылки на два других узла, соответствующих элементам с номерами2k+1и2k+2. Корень дерева соответствует элементу с номером0(ноль).

Дальнейшие действия следующие - массив переупорядочивается так, чтобы для любого kвыполнялись неравенства:

Затем массив еще раз переупорядочивается, уже по возрастанию номеров. Каждый из этих шагов требует операций.

Естественно, такой алгоритм работает быстрее и требует меньше памяти, но, наверное, он еще менее очевиден, чем рекурсивный.

Работа алгоритма пирамидальной сортировки начинается с вызова проце­дуры BuilD_Max__HEAP, с помощью которой из входного массиваA[1..n], где

n=length [А], создается невозрастающая пирамида. Поскольку наибольший эле­мент массива находится в корне, т.е. в элементеА [1], его можно поместить в окон­чательную позицию в отсортированном массиве, поменяв его местами с элемен­томА [п]. Выбросив из пирамиды узелп (путем уменьшения на единицу величиныhcap_size [А]}, мы обнаружим, что подмассивА [1.. (n- 1)] легко преобразуется в невозрастающую пирамиду. Пирамиды, дочерние по отношению к корневому узлу, после обмена элементовA[1] и А [n] и уменьшения размера массива остают­ся невозрастающими, однако новый корневой элемент может нарушить свойство невозрастания пирамиды. Для восстановления этого свойства достаточно вызвать процедуруМах_НеаРIFY(A,1), после чего подмассивА [1.. (n— 1)] превратится в невозрастающую пирамиду. Затем алгоритм пирамидальной сортировки повто­ряет описанный процесс для невозрастающих пирамид размераn-1,n-2,... ,2.

Heapsort(A)

1 Build_Max_Heap(A)

2 for i tength[A] downto 2

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

  1. heap_size[A]hеар_size[A] - 1

  2. Max_Heapify(A, 1)

На рис. 5.4 показан пример пирамидальной сортировки после предваритель­ного построения невозрастающей пирамиды. В каждой части этого рисунка изоб­ражена невозрастающая пирамида перед выполнением очередной итерации цикла forв строках 2-5. В частиа) этого рисунка показана исходная невозрастающая пирамида, полученная при помощи процедурыBU1LD_MAX_HEAP. В частяхб)-к) показаны пирамиды, получающиеся в результате вызова процедурыMAX_HEAPIFYв строке 5. В каждой из этих частей указано значение индексаi. В пирамиде со­держатся только узлы, закрашенные светло-серым цветом. В части л) показан получившийся в конечном итоге массивА.

Время работы процедуры Heapsort равно О (nlgn), поскольку вызов про­цедурыBuild_Max_Heap требует времени0(п), а каждый изп — 1 вызовов процедурыMax_Heapify — времениО (lgn).

Рис. 5.4. Работа процедуры Heapsort.

Приведем псевдокоды процедур BU1LD_MAX_HEAP(создание пирамиды из неупорядоченного массива данных) иMAX_HEAPIFY(поддержка свойств пирамиды).

Max_Heapify(A,j)

  1. l LEFT(i)

  2. r RlGHT(i)

  3. if l heap_size[A] и А[l] > A[i]

  1. then largestl

  2. else largest i

6 if r heap_size[A] и A[r] > A[largest]

7 then largest r

8 if largest i

9 then Обменять A[i] A[largest] 10 MaX_HeaPIFY(A, largest)

Build_Max_Heap(A)

  1. heap_size[A] length[A]

  2. for i downto 1

3 do MAX_HEAPIFY(A, i)

Соседние файлы в папке Шаповалов