Алгоритм сортировки Шелла (Shell Sort): принцип работы

Модуль "Сортировки" • урок 5 из 17 •

Также упоминается как: Сортировка с убывающим шагом, Метод Шелла

Суть урока. Сортировка Шелла (Shell Sort): улучшенная вставка. Сравнивает и сдвигает элементы с определенным шагом (gap), который постепенно уменьшается до 1. Позволяет элементам перепрыгивать большие дистанции. Сложность O(N1.25) до O(N²), неустойчива.

Предложенная Дональдом Шеллом, эта сортировка стала одним из первых алгоритмов, пробивших "стеклянный потолок" сложности O(N²).

Главная проблема обычных вставок в том, что элементы сдвигаются только на одну позицию. Если минимальный элемент находится в конце, ему придется "проползти" N шагов. Шелл предложил применять сортировку вставкой к подпоследовательностям, составленным из элементов, отстоящих друг от друга на некоторый шаг (gap).

Идея метода сортировки

Алгоритм сортировки Шелла: попарное сравнение с убывающим шагом
Сортировка Шелла: попарное сравнение и обмен элементов с убывающим шагом (gap) для быстрого устранения далеких инверсий.

Интерактивный блок помогает понять ключевую особенность сортировки Шелла - сравнение и обмен элементов не подряд, а с убывающим шагом.

Тренажер: алгоритм сортировки Шелла

Отсортируем массив 7 4 6 5 2 3 1 с убывающим шагом (gap).

не на месте пара через gap отсортировано
gap: - Сравнения: 0 Прыжки: 0 Шаг: 0 / 0
///
Shell Sort
Сортировка Шелла
Улучшенная сортировка вставкой: элементы сравниваются и обмениваются на больших расстояниях, которые постепенно уменьшаются до единицы.
Разобрать по шагам в большой версии →

В зависимости от выбранной последовательности шагов, средняя сложность сортировки Шелла составляет от 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), быстро устраняя далекие инверсии.

Проверьте себя

За счет чего сортировка Шелла работает быстрее классической сортировки вставкой?

Как вам урок? Спасибо за отзыв!