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

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

Очередь с приоритетами — это структура данных, состоящая из элементов с ключами, которая поддерживает две основные операции: вставить (insert) новый элемент и извлечь (remove) элемент с наибольшим ключом.

Имеется возможность модифицировать так, чтобы сортировка массива не требовала дополнительной памяти — организовав пирамидальное дерево внутри сортируемого массива. Другими словами, перейдя к задаче сортировки, мы не будем скрывать очередь с приоритетами, и вместо того чтобы держаться в рамках интерфейса АТД очереди с приоритетами, будем непосредственно вызывать функции fixUp и fixDown.

Пирамидальная сортировка (она же сортировка кучей) – классический алгоритм который, пожалуй, должен знать любой программист. Представлена на рисунке 8.

Рисунок 8

Код реализации:

#include <iostream>

 

void iswap (int&n1, int&n2) {

int temp = n1;

n1 = n2;

n2 = temp;

}

 

int main () {

unsigned const n = 100u;

int a[n];

 

// Для наглядности заполняем массив числами от n до 0.

for (unsigned i = 0u; i< n; ++i) {

a[i] = n - i;

std::cout<< a[i] << ' ';

}

 

// ----------- Сортировка ------------

// Сортирует по возрастанию. Чтобы получить сортировку по убыванию,

// поменяйте знаки сравнения в строчках, помеченных /*(знак)*/

unsigned sh = 0u; // Смещение

bool b;

do {

b = false;

for (unsigned i = 0u; i< n; ++i) {

if (i * 2 + 2 + sh< n) {

if ((a[i + sh] > /*<*/ a[i * 2 + 1 + sh]) || (a[i + sh] > /*<*/ a[i * 2 + 2 + sh])) {

if (a[i * 2 + 1 + sh] < /*>*/ a[i * 2 + 2 + sh]) {

iswap(a[i + sh], a[i * 2 + 1 + sh]);

b = true;

} elseif (a[i * 2 + 2 + sh] < /*>*/ a[i * 2 + 1 + sh]) {

iswap(a[i + sh], a[i * 2 + 2 + sh]);

b = true;

}

}

// Дополнительная проверка для последних двух элементов;

// с её помощью можно отсортировать пирамиду

// состоящую всего лишь из трёх элементов

if (a[i * 2 + 2 + sh] < /*>*/ a[i * 2 + 1 + sh]) {

iswap(a[i * 2 + 1 + sh], a[i * 2 + 2 + sh]);

b = true;

}

} elseif (i * 2 + 1 + sh< n) {

if (a[i + sh] > /*<*/ a[ i * 2 + 1 + sh]) {

iswap(a[i + sh], a[i * 2 + 1 + sh]);

b = true;

}

}

}

if (!b)

++sh; // Смещение увеличивается, когда на текущем этапе сортировать больше нечего

} while (sh + 2 < n); // Конец сортировки

 

std::cout<<std::endl<<std::endl;

for (unsigned i = 0u; i< n; ++i)

std::cout<< a[i] << ' ';

 

return 0;

}

 


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: