Алгоритм сортировки Шелла (Shell Sort): принцип работы
Также упоминается как: Сортировка с убывающим шагом, Метод Шелла
Предложенная Дональдом Шеллом, эта сортировка стала одним из первых алгоритмов, пробивших "стеклянный потолок" сложности O(N²).
Главная проблема обычных вставок в том, что элементы сдвигаются только на одну позицию. Если минимальный элемент находится в конце, ему придется "проползти" N шагов. Шелл предложил применять сортировку вставкой к подпоследовательностям, составленным из элементов, отстоящих друг от друга на некоторый шаг (gap).
Идея метода сортировки
- Начинаем с большого шага (например,
gap = N / 2). Применяем алгоритм вставки к элементам на этом расстоянии друг от друга. Маленькие элементы совершают "гигантские скачки" в левую часть массива! - Уменьшаем шаг (обычно вдвое:
gap = gap / 2) и повторяем процесс сортировки. - На последней итерации
gap = 1- это классическая сортировка вставкой. Но так как массив уже был "грубо" отсортирован, последний проход отрабатывает практически за O(N).
Интерактивный блок помогает понять ключевую особенность сортировки Шелла - сравнение и обмен элементов не подряд, а с убывающим шагом.
Тренажер: алгоритм сортировки Шелла
Отсортируем массив 7 4 6 5 2 3 1 с убывающим шагом (gap).
В зависимости от выбранной последовательности шагов, средняя сложность сортировки Шелла составляет от O(N1.25) до O(N1.5). Она сортирует массив "на месте", не требует выделения дополнительной памяти и обходится без рекурсии, что исторически делало ее популярной в системном программировании.
Реализация на языке C
void ShellSort(int arr[], int n) {
// Начинаем с большого шага (gap = половина массива), затем уменьшаем его вдвое
for (int gap = n / 2; gap > 0; gap /= 2) {
// Выполняем сортировку вставкой для элементов, разделенных шагом (gap)
for (int i = gap; i < n; i += 1) {
int temp = arr[i];
int j;
// Сдвигаем элементы с шагом (gap)
for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) {
arr[j] = arr[j - gap];
}
// Ставим элемент на место
arr[j] = temp;
}
}
}
Сравнение алгоритмов
- Вставка: Базовый алгоритм. O(N²), устойчив. Сдвигает элементы строго на одну позицию, из-за чего медленно переносит их в начало массива.
- Шелла: Улучшенная вставка. ≈O(N1.25), неустойчив. Позволяет элементам перепрыгивать сразу через расстояние (gap), быстро устраняя далекие инверсии.
Проверьте себя
За счет чего сортировка Шелла работает быстрее классической сортировки вставкой?