Сортировка Шелла
Пошаговая визуализация сортировки Шелла
Сортировка с шагами 23, 10, 4, 1.
Автор Дональд Шелл[1]
Предназначение Алгоритм сортировки
Структура данных Массив
Худшее время
Лучшее время
Среднее время зависит от выбранных шагов
Затраты памяти всего, дополнительно
Сортировка Шелла на примере

Сортировка Шелла (англ. Shell sort) — алгоритм сортировки, являющийся усовершенствованным вариантом сортировки вставками. Идея метода Шелла состоит в сравнении элементов, стоящих не только рядом, но и на определённом расстоянии друг от друга. Иными словами — это сортировка вставками с предварительными «грубыми» проходами. Аналогичный метод усовершенствования пузырьковой сортировки называется сортировка расчёской.

Описание

править

При сортировке Шелла сначала сравниваются и сортируются между собой значения, стоящие один от другого на некотором расстоянии (о выборе значения см. ниже). После этого процедура повторяется для некоторых меньших значений , а завершается сортировка Шелла упорядочиванием элементов при (то есть обычной сортировкой вставками). Эффективность сортировки Шелла в определённых случаях обеспечивается тем, что элементы «быстрее» встают на свои места (в простых методах сортировки, например, пузырьковой, каждая перестановка двух элементов уменьшает количество инверсий в списке максимум на 1, а при сортировке Шелла это число может быть больше).

Невзирая на то, что сортировка Шелла во многих случаях медленнее, чем быстрая сортировка, она имеет ряд преимуществ:

  • отсутствие потребности в памяти под стек;
  • отсутствие деградации при неудачных наборах данных — быстрая сортировка легко деградирует до , что хуже, чем худшее гарантированное время для сортировки Шелла.

История

править

Сортировка Шелла была названа в честь её изобретателя — Дональда Шелла, который опубликовал этот алгоритм в 1959 году.

Пример

править
Иллюстрация сортировки Шелла.

Пусть дан список и выполняется его сортировка методом Шелла, а в качестве значений выбраны .

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

В полученном списке на втором шаге вновь сортируются подсписки из отстоящих на 3 позиции элементов.

Процесс завершается обычной сортировкой вставками получившегося списка.

Выбор длины промежутков

править

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

  • первоначально используемая Шеллом последовательность длин промежутков: в худшем случае, сложность алгоритма составит ;
  • предложенная Хиббардом последовательность: все значения ; такая последовательность шагов приводит к алгоритму сложностью ;
  • предложенная Седжвиком последовательность: , если i четное и , если i нечетное. При использовании таких приращений средняя сложность алгоритма составляет: , а в худшем случае порядка . При использовании формулы Седжвика следует остановиться на значении inc[s-1], если 3*inc[s] > size.[2];
  • предложенная Праттом последовательность: все значения ; в таком случае сложность алгоритма составляет ;
  • эмпирическая последовательность Марцина Циура (последовательность A102549 в OEIS): ; является одной из лучших для сортировки массива ёмкостью приблизительно до 4000 элементов.[3];
  • эмпирическая последовательность, основанная на числах Фибоначчи: .

Реализация на языках программирования

править

C++

править
template<typename RandomAccessIterator, typename Compare>
void shell_sort( RandomAccessIterator first, RandomAccessIterator last, Compare comp )
{
    for( auto d = ( last - first ) / 2; d != 0; d /= 2 )
        for( auto i = first + d; i != last; ++i )
            for( auto j = i; j - first >= d && comp( *j, *( j - d ) ); j -= d )
                std::swap( *j, *( j - d ) );
}

Си

править
void check_and_swap(int i, int shift, int* nums) {
	for (int j = i - shift; j >= 0; j -= shift)
		if (nums[j] > nums[j + shift]) {
			int temp = nums[j];
			nums[j] = nums[j + shift];
			nums[j + shift] = temp;
		}
}
void shell_sort(int *array, int size) {
    for (int s = size / 2; s > 0; s /= 2) 
    {
        if (s > 1)
            for (int s_add = 0; s_add < s - 1; s_add++)
                for (int i = s + s_add; i < size; ++i) 
                    check_and_swap(i, s, array); 
        else
            for (int i = s; i < size; ++i) 
                check_and_swap(i, s, array); 
    }
}

Java

править
void shell_sort(List<Integer> array) {
        for (int s = array.size() / 2; s > 0; s /= 2)
            for (int i = s; i < array.size(); ++i)
                for (int j = i - s; j >= 0 && array.get(j) > array.get(j + s); j -= s) Collections.swap(array, j, j + s);
}

Python

править
def shell_sort(data: list[int]) -> list[int]:
    last_index = len(data)
    step = len(data)//2
    while step > 0:
        for i in range(step, last_index, 1):
            j = i
            delta = j - step
            while delta >= 0 and data[delta] > data[j]:
                data[delta], data[j] = data[j], data[delta]
                j = delta
                delta = j - step
        step //= 2
    return data

Примечания

править
  1. Shell D. L. A high-speed sorting procedure (англ.) // Communications of the ACM — New York City: Association for Computing Machinery, 1959. — Vol. 2, Iss. 7. — P. 30—32. — ISSN 0001-0782; 1557-7317doi:10.1145/368370.368387
  2. J. Incerpi, R. Sedgewick, «Improved Upper Bounds for Shellsort», J. Computer and System Sciences 31, 2, 1985.
  3. Marcin Ciura Best Increments for the Average Case of Shellsort. Дата обращения: 15 сентября 2009. Архивировано 30 августа 2011 года.

Ссылки

править

📚 Artikel Terkait di Wikipedia

Norton Utilities

Разработчики — компании Peter Norton Computing и Symantec (которая в сентябре 1990 года приобрела Peter Norton Computing). Последняя коммерческая версия —

GNOME

качестве оболочки по умолчанию, начиная с GNOME 3.0, используется GNOME Shell, основанная на оконном менеджере Mutter. Также до релиза GNOME 3.8 был доступен

Блокчейн

число компаний-основателей komgo SA вошли BNP Paribas, ING, Citigroup, Shell plc, The Bank of Tokyo-Mitsubishi UFJ, ABN AMRO и Crédit Agricole. В российском

CPython

Computer. Ubuntu 16.04 - End of Life in 2021 - SCS Computing Facilities - Carnegie Mellon University . computing.cs.cmu.edu. Дата обращения: 15 февраля 2021

Solus project

основано на GNOME, но использует собственные реализации оболочки GNOME Shell, панели, апплетов и системы вывода уведомлений. Budgie не является форком

Йоноска, Наташа

International Journal of Foundations of Computer Science, Computability и Natural Computing. В 2022 году она была удостоена стипендии Саймонса. В 2013 году с её участием

IBM 5151

обновления 50 Гц. Он использует цифровые входы TTL через 9-контактный разъём D-shell и может отображать как минимум три уровня яркости в соответствии с сигналами

Kotlin

параметров командной строки. Программы на Kotlin также поддерживают perl- и shell-стиль интерполяции строк (переменные, включённые в строку, заменяются на