Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
A+V.docx
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
366.71 Кб
Скачать

Сортировка

После построения пирамиды запускается процедура сортировки. Из пирамиды изымается вершина, ставится вначале будущей отсортированной последовательности. На ее место помещается конечный элемент пирамиды и просеивается через нее, занимая положенное ему место. В итоге на вершину восходит снова максимальный элемент. На втором шаге снова вершина снова перемещается в конечную последовательность и т.д. до тех пор пока вся пирамида не кончится.

Этот алгоритм уже будет сортировать все как нам надо и также быстро, но будет использовать дополнительную память под новую последовательность. Этого можно избежать путем введения в своем роде "хака" в пирамиду. Что если мы на каждом шаге вершину будем не изымать, а просто обменивать с конечным элементом пирамиды? Естественно с тем конечным элементом, который еще обменивался с вершиной, т.е. чтобы снова не обменивать уже раз поставленные вершины на предыдущих шагах в конец? В этом случае наша пирамида будет просто постепенно вырождаться в отсортированную последовательность, которая нам и нужна.

Алгоритм:

  1. Устанавливаем границы пирамиды c 0 по n-1, т.е. на данном этапе вся пирамида x[0..n-1] А вершина(heap) = 0 и конец(tail) = n-1

  2. Меняем x[heap] и x[tail]

  3. Корректируем tail = tail - 1

  4. Просеиваем новую вершину x[0] через пирамиду x[1..tail].

  5. Если tail = 1, то конец сортировки, иначе - п.2.

Для нашей построенной в предыдущем примере пирамиды, получим:

  1. Обмен x[0]=100, x[9]=2; просеивание x[0]=2 через [82 53 23 5 36 44 22 15] Получим: [82 23 53 22 5 36 44 2 15 100]*.

  2. Обмен x[0]=82 и x[8]=15, просеивание x[0]=15 через [23 53 22 5 36 44 2] Получим: [53 23 44 22 5 36 15 2 82 100]*

  3. Обмен x[0]=53 и x[7]=2, просеивание x[0]=53 через [23 44 22 5 36 15] Получим: [44 23 36 22 5 2 15 53 82 100]*

  4. Обмен x[0]=44 и x[6]=15, просеивание x[0]=44 через [23 36 22 5 2] Получим: [36 23 15 22 5 2 44 53 82 100]*

  5. Обмен x[0]=36 и x[5]=2, просеивание x[0]=2 через [23 15 22 5] Получим: [23 22 15 2 5 36 44 53 82 100]*

  6. Обмен x[0]=23 и x[4]=5, просеивание x[0]=5 через [23 15 2] Получим: [22 5 15 2 23 36 44 53 82 100]*

  7. Обмен x[0]=22 и x[3]=2, просеивание x[0]=2 через [5 15] Получим: [15 5 2 22 23 36 44 53 82 100]*

  8. Обмен x[0]=15 и x[2]=2, просеивание x[0]=2 через [5]. В данном случае все просеивание сведется к обмену x[0]=2 и x[1]=5. Получим: [5 2 15 22 23 36 44 53 82 100]*

  9. Обмен x[0]=2 и x[1]=5. Просеивание делать уже не имеет смысла. Однако если в конкретной реализации данного алгоритма оно запускается для такого случая - то процедура просеивания должна отличать такую ситуации и не делать никаких перестановок.

*Серым выделены элементы, которые как-бы изымаются из структуры пирамиды и представляют собой поэтапно формирующуюся искомую отсортированную последовательность. Они остаются в пирамиде просто для того, чтобы не расходовать доп. памяти на их новое хранение. Под пирамидой поэтому уже подразумевается последовательсность без этих серых элементов.

В результате получили искомую сортировку: x=[2 5 15 22 23 36 44 53 82 100], что и требовалось.

Псевдокод будет иметь вид:

 псевдокод: пирамидальная сортировка   

  1. // Построение пирамиды

  2. for i = n/2 - 1 downto 0

  3. Screening(x, i, n-1) // Процедура просеивания

  4.  

  5.  

  6. /* Формирование конечной отсортированной

  7. последовательности + "балансирование"

  8. пирамиды */

  9. for i = n-1 downto 1

  10. // меняем первый с последним

  11. swap(x, 0, i)

  12.  

  13. /* Восстановление баланса

  14. для пирамиды x[0..i-1] */

  15. Screening(x, 0, i-1)

  16.  

Построение процедуры как уже отмечено выше занимает максимум ~O(n*log n) времени. Описанная фаза сортировки - максимум тоже ~O(n*log n). С среднем ~O(n/2 * log n) конечно. В итоге получаем метод, который сортирует за ~O(n*log n) времени и не использует дополнительной памяти.

Следует отметить, что если сравнивать с другой сортировкой порядка ~O(n*log n) такой как быстрая сортировка - то вторая выигрывает по производительности, но при этом как известно расходует намного больше памяти.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]