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

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

a[i] ≤ a[2i+1];

a[i] ≤ a[2i+2].

Общая идея пирамидальной сортировки заключается в том, что сначала строится пирамида из элементов исходного массива, а затем осуществляется сортировка элементов. Алгоритм основан на одном из свойств кучи — в голове (или вершине) кучи находится самый (максимальный) элемент. Просеивание – это построение новой пирамиды посредством спуска вниз элемента из вершины дерева в соответствии с ключом сортировки

Алгоритм

  1. Построим из требуемого массива кучу

  2. Меняем местами первый и последний элемент в куче

  3. Уменьшаем размер рассматриваемой кучи на 1

  4. Вызвать процедуру нормализации кучи в корне кучи

  5. Вернуться в шаг 2 и продолжать выполнять алгоритм, пока куча имеет больше одного элемента

Выполнение алгоритма разбивается на два этапа. 1 этап Построение пирамиды.

2 этап Сортировка на построенной пирамиде.

Реализация на С++ (сортировка по возрастанию):

// Функция "просеивания" через кучу - формирование кучи

void siftDown(int *numbers, int root, int bottom)

{

int maxChild; // индекс максимального потомка

int done = 0; // флаг того, что куча сформирована

// Пока не дошли до последнего ряда

while ((root * 2+1 <= bottom) && (!done))

{

if (root * 2+1 == bottom) // если мы в последнем ряду,

maxChild = root * 2; // запоминаем левый потомок

// иначе запоминаем больший потомок из двух

else if (numbers[root * 2+1] > numbers[root * 2 + 2])

maxChild = root * 2+1;

else

maxChild = root * 2 + 2;

// если элемент вершины меньше максимального потомка

if (numbers[root] < numbers[maxChild])

{

int temp = numbers[root]; // меняем их местами

numbers[root] = numbers[maxChild];

numbers[maxChild] = temp;

root = maxChild;

}

else // иначе

done = 1; // пирамида сформирована

}

}

// Функция сортировки на куче

void heapSort(int *numbers, int array_size)

{

// Формируем нижний ряд пирамиды

for (int i = (array_size / 2) - 1; i >= 0; i--)

siftDown(numbers, i, array_size);

// Просеиваем через пирамиду остальные элементы

for (int i = array_size - 1; i >= 1; i--)

{

int temp = numbers[0];

numbers[0] = numbers[i];

numbers[i] = temp;

siftDown(numbers, 0, i - 1);

}

}

      1. Метод Хоара

Сортировка Хоара – это одна из разновидностей быстрых сортировок, основанная на упорядочивании подмножеств массива относительно опорных элементов.

Быстрая сортировка, сортировка Хоара (англ. quicksort), часто называемая qsort (по имени в стандартной библиотеке языка Си) — широко известный алгоритм сортировки, разработанный английским информатиком Чарльзом Хоаром во время его работы в МГУ в 1960 году.

Один из самых быстрых известных универсальных алгоритмов сортировки массивов: в среднем O(n\log n) обменов при упорядочении n элементов.

На входе массив a[0]...a[N] и опорный элемент x, по которому будет производиться разделение.

  1. Введем два указателя: i и j. В начале алгоритма они указывают, соответственно, на левый и правый конец последовательности.

  2. Будем двигать указатель i с шагом в 1 элемент по направлению к концу массива, пока не будет найден элемент a[i] >= x. Затем аналогичным образом начнем двигать указатель j от конца массива к началу, пока не будет найден a[j] <= x.

  3. Д алее, если i <= j, меняем a[i] и a[j] местами и продолжаем двигать i,j по тем же правилам...

  4. Повторяем шаг 3, пока i <= j.

Реализация на С++:

void qs(int* s_arr, int first, int last)

{

//i - первый элемент, j - последний, x - средний

int i = first, j = last, x = s_arr[(first + last) / 2];

do {

//доходим до элемента который больше х

while (s_arr[i] < x) i++;

//доходим до элемента который меньше х

while (s_arr[j] > x) j--;

if (i <= j) {

//меняем местами

if (s_arr[i] > s_arr[j])

swap(s_arr[i], s_arr[j]);

i++;

j--;

}

} while (i <= j);

//рекурсивно сортируем каждую часть

if (i < last)

qs(s_arr, i, last);

if (first < j)

qs(s_arr, first, j);

}