Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Пособие часть 1.doc
Скачиваний:
60
Добавлен:
24.09.2019
Размер:
6.98 Mб
Скачать

Первая фаза сортировки пирамидой

Сортировка пирамидой включает в себя две фазы. На первой фазе мы преобразуем исходную последовательность в пирамиду. Как правило, пирамида строится прямо в исходном массиве, и дополнительная память не требуется.

Итак, пусть задан массив a из n элементов. Заметим, что элементы с индексами in/2 заведомо не превосходят своих детей, поскольку таковых не имеют (индексы i∙2+1 и i∙2+2 выходят за границы массива). Чтобы это свойство пирамиды выполнялось и для других элементов, поступим следующим образом. Будем двигаться по массиву справа налево, начиная с индекса n/2-1. Встав на очередной элемент a[i], выберем максимального из его сыновей a[i∙2+1] и a[i∙2+2] (не забывая при этом, что у элемента может быть только один сын или не быть их вовсе). Если максимальный из сыновей не превосходит родителя, то всё в порядке, иначе поменяем их местами и выполним аналогичную проверку для нашего элемента уже на его новом месте. Возможно, этот шаг придётся выполнить несколько раз. Пример показан на рис. 4.6.

0

I=1

2

3

4

5

6

7

3

4

7

8

5

6

5

5

0

I=1

2

3

4

5

6

7

3

8

7

4

5

6

5

5

0

I=1

2

3

4

5

6

7

3

8

7

5

5

6

5

4

Рис 4.8. Элемент 4 "проваливается" в пирамиду.

Приведём пример функции, выполняющей “погружение” очередного элемента вглубь пирамиды. Параметрами функции будут исходный массив a, его длина n и индекс элемента i.

void downheap(int a[], int n, int i)

{

while (i<n/2) //при i>=n/2 детей нет, и основное свойство

{ //пирамиды выполняется тривиальным образом

//определяем максимального из сыновей

int i_max = i*2+1;

if (i_max+1<n) //второго сына может и не быть

if (a[i_max+1]>a[i_max])

i_max=i_max+1;

//проверяем, выполняется ли основное свойство пирамиды

if (a[i]>=a[i_max]) break;

//меняем местами элемент и его сына и корректируем i

int tmp = a[i]; a[i] = a[i_max]; a[i_max] = tmp;

i = i_max;

}

}

Теперь чтобы преобразовать исходный массив в пирамиду, осталось только вызвать функцию downheap для всех элементов от n/2-1 до 0:

for(int i=n/2-1; i>=0; i--) downheap(a,n,i);

Вторая фаза сортировки пирамидой

На второй фазе полученная пирамида преобразуется в отсортированный массив. Это делается следующим образом. Из основного свойства пирамиды следует, что максимальный элемент находится на её вершине, то есть это элемент a[0]. Поменяем местами элемент a[0] c последним элементом массива – a[n-1]. В результате a[0] встанет на своё конечное место (действительно, раз он наибольший, то после сортировки должен стоять в самом конце).

Чтобы этот элемент больше не рассматривать, уменьшим на 1 длину массива (исходную длину мы предварительно запомним).

Наконец, вызвав функцию downheap() для элемента a[0], мы снова получим пирамиду, только в ней будет на один элемент меньше.

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

for(int i=n-1; i>0; i--)

{ // a[0] - сейчас максимальный элемент среди a[0]..a[i]

// поставим его на своё место

int tmp = a[i]; a[i] = a[0]; a[0] = tmp;

// восстановим пирамидальность оставшейся части массива

downheap(a,i,0);

}