Пирамидальная сортировка
Пирамидальная сортировка (Heapsort, сортировка кучей) подходит для работы с полными бинарными деревьями в массиве. В ней используется структура данных, называемая кучей. Пирамида (сортирующее дерево, двоичная куча) – это двоичное дерево с упорядоченными листьями, в корне которого расположен максимальный или минимальный элемент.Пирамидой (кучей) называется двоичное дерево такое, что
a[i] ≤ a[2i+1];
a[i] ≤ a[2i+2].
Общая идея пирамидальной сортировки заключается в том, что сначала строится пирамида из элементов исходного массива, а затем осуществляется сортировка элементов. Алгоритм основан на одном из свойств кучи — в голове (или вершине) кучи находится самый (максимальный) элемент. Просеивание – это построение новой пирамиды посредством спуска вниз элемента из вершины дерева в соответствии с ключом сортировки
Алгоритм
Построим из требуемого массива кучу
Меняем местами первый и последний элемент в куче
Уменьшаем размер рассматриваемой кучи на 1
Вызвать процедуру нормализации кучи в корне кучи
Вернуться в шаг 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);
}
}
Метод Хоара
Сортировка Хоара – это одна из разновидностей быстрых сортировок, основанная на упорядочивании подмножеств массива относительно опорных элементов.
Быстрая сортировка, сортировка Хоара (англ. quicksort), часто называемая qsort (по имени в стандартной библиотеке языка Си) — широко известный алгоритм сортировки, разработанный английским информатиком Чарльзом Хоаром во время его работы в МГУ в 1960 году.
Один из самых быстрых известных универсальных алгоритмов сортировки массивов: в среднем O(n\log n) обменов при упорядочении n элементов.
На входе массив a[0]...a[N] и опорный элемент x, по которому будет производиться разделение.
Введем два указателя: i и j. В начале алгоритма они указывают, соответственно, на левый и правый конец последовательности.
Будем двигать указатель i с шагом в 1 элемент по направлению к концу массива, пока не будет найден элемент a[i] >= x. Затем аналогичным образом начнем двигать указатель j от конца массива к началу, пока не будет найден a[j] <= x.
Д
алее,
если i <= j, меняем a[i] и a[j] местами и
продолжаем двигать i,j по тем же правилам...Повторяем шаг 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);
}
