Введение

Сравнительный алгоритм сортировки
В информатике адаптивная сортировка кучей — это сравнительный алгоритм сортировки из семейства адаптивных алгоритмов сортировки. Это вариант сортировки кучей, который показывает лучшие результаты, когда данные уже частично упорядочены. Алгоритм, опубликованный Христосом Левкопулосом и Олой Петерссоном в 1992 году, использует новую меру предварительной упорядоченности, Osc, определяемую как количество осцилляций. В отличие от традиционной сортировки кучей, которая помещает все данные в кучу, адаптивная сортировка кучей помещает в кучу только часть данных, что значительно сокращает время выполнения при высокой степени предварительной упорядоченности. Обычно алгоритм включает следующие четыре шага. Построение Max-кучи (Min-кучи): поместите все данные в кучу так, чтобы каждый узел был больше или равен (меньше или равен для Min-кучи) каждому из его дочерних узлов. Поменяйте местами первый и последний элементы кучи. Удалите последний элемент из кучи и поместите его в конец списка. Восстановите структуру кучи, чтобы первый элемент оказался на своем месте. Повторяйте шаги 2 и 3, пока в куче не останется только один элемент. Поместите этот последний элемент в конец списка и выведите отсортированный список. Ниже представлена реализация на C/C++, которая строит Max-кучу и сортирует массив после ее построения. /* Пример кода сортировки кучей на C/C++, сортирующий массив по возрастанию */ // Функция для построения Max-кучи (бинарного дерева) void heapify(int array[], int start, int end) { int parent = start; int child = parent * 2 + 1; while (child <= end) { if (child + 1 <= end) // если есть два дочерних узла { if (array[child + 1] > array[child]) { child++; // выбрать больший дочерний узел } } if (array[parent] > array[child]) { return; // если родительский узел больше, куча уже построена } if (array[parent] < array[child]) // если дочерний узел больше родительского { swap(array[parent], array[child]); // поменять родительский и дочерний узлы parent = child; child = child * 2 + 1; // продолжить цикл, сравнить дочерний узел с его дочерними узлами } } } // Функция сортировки кучей void heap_sort(int array[], int len) { for (int i = len / 2 - 1; i >= 0; i--) // Шаг 1: построение Max-кучи { heapify(array, i, len - 1); } for (int i = len - 1; i >= 0; i--) // Шаг 4: повторение шагов 2 и 3 до завершения { swap(array[0], array[i]); // Шаг 2: поместить максимальный элемент в конец массива heapify(array, 0, i - 1); // Шаг 3: удалить максимальный элемент из кучи и восстановить ее } } int main() { // Массив для сортировки int array[] = {42, 1283, 123, 654, 239847, 45, 97, 85, 763, 90, 770, 616, 328, 1444, 911, 315, 38, 5040, 1}; int array_len = sizeof(array) / sizeof(*array); // Длина массива heap_sort(array, array_len); return 0; }

Меры предварительного сортирования

Меры предсортированности оценивают существующий порядок в заданной последовательности. Эти меры предсортированности определяют объем данных, которые будут помещены в кучу в процессе сортировки, а также нижнюю границу времени выполнения.

Недостатки

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