Сорт | Алгоритм сортировки |
---|---|
Структура данных | Множество |
Худший вариант производительности | O( n 2 ) (наихудшая известная последовательность зазоров в худшем случае) O( n log 2 n ) (наиболее известная последовательность зазоров в худшем случае) [1] |
Лучшая производительность | O( n log n ) (большинство последовательностей зазоров) O( n log 2 n ) (самая известная наихудшая последовательность зазоров) [2] |
Средняя производительность | зависит от последовательности пробелов |
Наихудшая сложность пространства | О( n ) всего, О(1) вспомогательных |
Оптимальный | Нет |
Сортировка Шелла , также известная как сортировка Шелла или метод Шелла , является сортировкой сравнения на месте . Ее можно рассматривать как обобщение сортировки обменом ( пузырьковая сортировка ) или сортировки вставкой ( сортировка вставкой ). [3] Метод начинается с сортировки пар элементов, далеко отстоящих друг от друга, а затем постепенно сокращает зазор между сравниваемыми элементами. Начиная с далеко отстоящих элементов, он может переместить некоторые элементы, находящиеся не на своих местах, в положение быстрее, чем простой обмен ближайшими соседями. Дональд Шелл опубликовал первую версию этой сортировки в 1959 году. [4] [5] Время выполнения сортировки Шелла сильно зависит от последовательности зазоров, которую она использует. Для многих практических вариантов определение их временной сложности остается открытой проблемой .
Сортировка Шелла — это оптимизация сортировки вставкой , которая позволяет обменивать элементы, которые находятся далеко друг от друга. Идея состоит в том, чтобы организовать список элементов таким образом, чтобы, начиная с любого места, взятие каждого h -го элемента давало отсортированный список. Такой список называется h -сортированным. Его также можно рассматривать как h -перемежающиеся списки, каждый из которых сортируется индивидуально. [6] Начало с больших значений h позволяет элементам перемещаться на большие расстояния в исходном списке, быстро уменьшая большой объем беспорядка и оставляя меньше работы для меньших шагов h -сортировки. [7] Если затем список отсортировать по k для некоторого меньшего целого числа k , то список останется h -сортированным. Окончательная сортировка с h = 1 гарантирует, что список будет полностью отсортирован в конце, [6] но разумно выбранная убывающая последовательность значений h оставляет очень мало работы для этого последнего прохода.
Проще говоря, это означает, что если у нас есть массив из 1024 чисел, наш первый промежуток ( h ) может быть 512. Затем мы пробегаемся по списку, сравнивая каждый элемент в первой половине с элементом во второй половине. Наш второй промежуток ( k ) равен 256, что разбивает массив на четыре секции (начиная с 0, 256, 512, 768), и мы убеждаемся, что первые элементы в каждой секции отсортированы относительно друг друга, затем второй элемент в каждой секции и т. д. На практике последовательность промежутков может быть любой, но последний промежуток всегда равен 1, чтобы завершить сортировку (фактически завершая обычную сортировку вставкой).
Ниже показан пример выполнения сортировки Шелла с интервалами 5, 3 и 1.
а 1 | а 2 | а 3 | а 4 | а 5 | а 6 | а 7 | а 8 | а 9 | а 10 | а 11 | а 12 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
Входные данные | 62 | 83 | 18 | 53 | 07 | 17 | 95 | 86 | 47 | 69 | 25 | 28 |
После 5-сортировки | 17 | 28 | 18 | 47 | 07 | 25 | 83 | 86 | 53 | 69 | 62 | 95 |
После 3-й сортировки | 17 | 07 | 18 | 47 | 28 | 25 | 69 | 62 | 53 | 83 | 86 | 95 |
После 1-сортировки | 07 | 17 | 18 | 25 | 28 | 47 | 53 | 62 | 69 | 83 | 86 | 95 |
Первый проход, 5-сортировка, выполняет сортировку вставкой для пяти отдельных подмассивов ( a 1 , a 6 , a 11 ), ( a 2 , a 7 , a 12 ), ( a 3 , a 8 ), ( a 4 , a 9 ), ( a 5 , a 10 ). Например, он изменяет подмассив ( a 1 , a 6 , a 11 ) с (62, 17, 25) на (17, 25, 62). Следующий проход, 3-сортировка, выполняет сортировку вставкой для трех подмассивов ( a 1 , a 4 , a 7 , a 10 ), ( a 2 , a 5 , a 8 , a 11 ), ( a 3 , a 6 , a 9 , a 12 ). Последний проход, 1-сортировка, представляет собой обычную сортировку вставкой всего массива ( a 1 ,..., a 12 ).
Как показывает пример, подмассивы, с которыми работает сортировка Шелла, изначально короткие; позже они становятся длиннее, но почти упорядоченными. В обоих случаях сортировка вставкой работает эффективно.
В отличие от сортировки вставкой , сортировка Шелла не является стабильной сортировкой , поскольку вставки с зазорами перемещают равные элементы друг мимо друга и, таким образом, теряют свой первоначальный порядок. Это адаптивный алгоритм сортировки , который выполняется быстрее, когда входные данные частично отсортированы.
Использование последовательности пробелов Марцина Чиуры с сортировкой внутренней вставкой.
# Сортировка массива a[0...n-1]. gaps = [ 701 , 301 , 132 , 57 , 23 , 10 , 4 , 1 ] # Последовательность пробелов Сиуры # Начинаем с самого большого пробела и уменьшаем до пробела 1 # аналогично сортировке вставкой, но вместо 1 на каждом шаге используется пробел foreach ( gap in gaps ) { # Выполняем сортировку вставкой с пробелами для каждого элемента в gaps # Каждый цикл оставляет a[0..gap-1] в порядке с пробелами for ( i = gap ; i < n ; i += 1 ) { # сохраняем a[i] в temp и создаем пробел в позиции i temp = a [ i ] # сдвигаем ранее отсортированные по пробелам элементы вверх, пока не будет найдено правильное местоположение для a[i] for ( j = i ; ( j >= gap ) && ( a [ j - gap ] > temp ); j -= gap ) { a [ j ] = a [ j - gap ] } # помещаем temp (исходный a[i]) в правильное местоположение a [ j ] = temp } }
Вопрос о том, какую последовательность пробелов использовать, сложен. Каждая последовательность пробелов, содержащая 1, дает правильную сортировку (поскольку это делает последний проход обычной сортировкой вставкой); однако свойства полученных таким образом версий сортировки Шелла могут сильно отличаться. Слишком мало пробелов замедляют проходы, а слишком много пробелов создают накладные расходы.
В таблице ниже сравниваются большинство предложенных последовательностей пробелов, опубликованных до сих пор. Некоторые из них имеют убывающие элементы, зависящие от размера сортируемого массива ( N ). Другие представляют собой возрастающие бесконечные последовательности, элементы которых, меньшие N, должны использоваться в обратном порядке.
ОЭИС | Общий термин ( k ≥ 1) | Бетонные щели | Наихудшая временная сложность | Автор и год публикации |
---|---|---|---|---|
[например, когда N = 2 p ] | Шелл , 1959 [4] | |||
Фрэнк и Лазарус, 1960 [8] | ||||
А000225 | Хиббард , 1963 [9] | |||
А083318 | , с префиксом 1 | Папернов и Стасевич, 1965 [10] | ||
А003586 | Последовательные числа вида ( 3-гладкие числа) | Пратт , 1971 [1] | ||
А003462 | , не более | Кнут , 1973, [3] на основе Пратта , 1971 [1] | ||
А036569 | Инсерпи и Седжвик , 1985, [11] Кнут [3] | |||
А036562 | , с префиксом 1 | Седжвик, 1982 [6] | ||
А033622 | Седжвик, 1986 [12] | |||
Неизвестный | Гоннет и Баеза-Йейтс , 1991 [13] | |||
А108870 | (или эквивалентно, ) | Неизвестный | Токуда, 1992 г. [14] (неправильная цитата согласно OEIS) | |
А102549 | Неизвестно (получено экспериментально) | Неизвестный | Сиура, 2001 [15] | |
А366726 | Неизвестный | Ли, 2021 [16] | ||
Неизвестный | Скин, Эренборг, Яромчик, 2023 г. [17] |
Когда двоичное представление N содержит много последовательных нулей, сортировка Шелла с использованием исходной последовательности зазоров Шелла производит Θ( N 2 ) сравнений в худшем случае. Например, этот случай имеет место для N , равного степени двойки, когда элементы больше и меньше медианы занимают нечетные и четные позиции соответственно, поскольку они сравниваются только в последнем проходе.
Хотя версия Пратта имеет более высокую сложность, чем O ( N log N ), которая является оптимальной для сортировок методом сравнения, она пригодна для сортировочных сетей и имеет ту же асимптотическую сложность вентилей, что и битонный сортировщик Батчера .
Гонне и Баеза-Йетс заметили, что сортировка Шелла в среднем делает наименьшее количество сравнений, когда отношения последовательных пробелов примерно равны 2,2. [13] Вот почему их последовательность с отношением 2,2 и последовательность Токуды с отношением 2,25 оказываются эффективными. Однако неизвестно, почему это так. Седжвик рекомендует использовать пробелы, которые имеют низкие наибольшие общие делители или являются попарно взаимно простыми . [18] [ неудавшаяся проверка ] Пробелы, которые являются нечетными числами, по-видимому, хорошо работают на практике: наблюдалось 25%-ное сокращение при избегании четных пробелов. Пробелы, которые избегают кратных 3 и 5, по-видимому, дают небольшие преимущества < 10%. [ оригинальное исследование? ]
Что касается среднего числа сравнений, то последовательность Сиуры [15] имеет наилучшую известную производительность; пробелы больше 701 не были определены, но последовательность может быть дополнительно расширена в соответствии с рекурсивной формулой .
Последовательность Токуды, определяемая простой формулой , где , , может быть рекомендована для практических приложений.
Если максимальный размер входных данных невелик, как это может произойти, если сортировка Шелла используется на небольших подмассивах другим рекурсивным алгоритмом сортировки, таким как быстрая сортировка или сортировка слиянием , то можно составить таблицу оптимальной последовательности для каждого размера входных данных. [19] [20]
Имеет место следующее свойство: после h 2 -сортировки любого h 1 -сортированного массива массив остается h 1 -сортированным. [21] Каждый h 1 -сортированный и h 2 -сортированный массив также ( a 1 h 1 + a 2 h 2 )-сортирован для любых неотрицательных целых чисел a 1 и a 2 . Таким образом, наихудшая сложность сортировки Шелла связана с задачей Фробениуса : для заданных целых чисел h 1 ,..., h n с gcd = 1 число Фробениуса g ( h 1 ,..., h n ) является наибольшим целым числом, которое не может быть представлено в виде a 1 h 1 + ... + a n h n с неотрицательным целым числом a 1 ,..., a n . Используя известные формулы для чисел Фробениуса, мы можем определить наихудшую сложность сортировки Шелла для нескольких классов последовательностей пробелов. [22] Доказанные результаты показаны в таблице выше.
Марк Аллен Вайс доказал, что сортировка Шелла выполняется за время O ( N log N ), когда входной массив находится в обратном порядке. [23]
Что касается среднего числа операций, ни один из доказанных результатов не касается практической последовательности пробелов. Для пробелов, которые являются степенями двойки, Эспелид вычислил это среднее значение как . [24] Кнут определил среднюю сложность сортировки N -элементного массива с двумя пробелами ( h , 1) как . [3] Из этого следует, что двухпроходная сортировка Шелла с h = Θ( N 1/3 ) в среднем выполняет O ( N 5/3 ) сравнений/инверсий/время выполнения. Яо нашел среднюю сложность трехпроходной сортировки Шелла. [25] Его результат был уточнен Янсоном и Кнутом: [26] среднее число сравнений/инверсий/время выполнения, выполненных во время сортировки Шелла с тремя пробелами ( ch , cg , 1), где h и g являются взаимно простыми числами, составляет в первом проходе, во втором проходе и в третьем проходе. ψ ( h , g ) в последней формуле — сложная функция, асимптотически равная . В частности, при h = Θ( N 7/15 ) и g = Θ( N 1/5 ) среднее время сортировки составляет O ( N 23/15 ).
На основе экспериментов высказано предположение, что сортировка Шелла с последовательностью пробелов Хиббарда выполняется в среднем за время O ( N 5/4 ) [3] и что последовательность Гонне и Баеза-Йетса требует в среднем 0,41 N ln N (ln ln N + 1/6) перемещений элементов. [13] Приближения среднего числа операций, ранее предложенные для других последовательностей, не работают, когда отсортированные массивы содержат миллионы элементов.
На графике ниже показано среднее число сравнений элементов, используемых различными последовательностями пробелов, деленное на теоретическую нижнюю границу , т.е. log 2 N !. Последовательность Чиурии 1, 4, 10, 23, 57, 132, 301, 701 (обозначенная Ci01) была расширена в соответствии с формулой .
Применяя теорию сложности Колмогорова , Цзян, Ли и Витаний [27] доказали следующую нижнюю границу для порядка среднего числа операций/времени выполнения в p -проходной сортировке Шелла: Ω( pN 1+1/ p ) при p ≤ log 2 N и Ω( pN ) при p > log 2 N . Таким образом, сортировка Шелла имеет перспективы выполнения за среднее время, которое асимптотически растет как N log N только при использовании последовательностей промежутков, число промежутков которых растет пропорционально логарифму размера массива. Однако неизвестно, может ли сортировка Шелла достичь этого асимптотического порядка сложности в среднем случае, который является оптимальным для сортировок сравнения. Нижняя граница была улучшена Витанием [ 28] для каждого числа проходов до , где . Этот результат подразумевает, например, нижнюю границу Цзян-Ли-Витаньи для всех -проходных последовательностей приращений и улучшает эту нижнюю границу для конкретных последовательностей приращений. Фактически, все границы (нижние и верхние), известные в настоящее время для среднего случая, точно соответствуют этой нижней границе. Например, это дает новый результат, что верхняя граница Янсона-Кнута соответствует результирующей нижней границе для используемой последовательности приращений, показывая, что трехпроходная сортировка Шелла для этой последовательности приращений использует сравнения/инверсии/время выполнения. Формула позволяет нам искать последовательности приращений, которые дают нижние границы, которые неизвестны; например, последовательность приращений для четырех проходов, которая имеет нижнюю границу больше, чем для последовательности приращений . Нижняя граница становится
Сложность любой версии сортировки Шелла в худшем случае имеет более высокий порядок: Плэкстон, Пунен и Суэл показали, что она растет по крайней мере так же быстро, как . [29] [30] Роберт Сайфер доказал более сильную нижнюю границу: когда для всех . [31]
Shellsort выполняет больше операций и имеет более высокий коэффициент промахов кэша , чем quicksort . Однако, поскольку он может быть реализован с использованием небольшого кода и не использует стек вызовов , некоторые реализации функции qsort в стандартной библиотеке C, ориентированные на встраиваемые системы, используют его вместо quicksort. Shellsort, например, используется в библиотеке uClibc . [32] По аналогичным причинам в прошлом Shellsort использовался в ядре Linux . [33]
Сортировка Шелла может также служить подалгоритмом интроспективной сортировки , чтобы сортировать короткие подмассивы и предотвращать замедление, когда глубина рекурсии превышает заданный предел. Этот принцип используется, например, в компрессоре bzip2 . [34]
Обширные эксперименты показывают, что последовательность, определяемая как α = 0,45454 < 5/11, работает значительно лучше, чем другие последовательности. Самый простой способ вычислить ⌊ 0,45454 n ⌋ — использовать целочисленную арифметику.(5 * n — 1)/11
{{cite book}}
: CS1 maint: location missing publisher (link)