Shellsort - Shellsort - Wikipedia

Shellsort
Пошаговая визуализация Shellsort
Shellsort с зазорами 23, 10, 4, 1 в действии
Учебный классАлгоритм сортировки
Структура данныхМножество
Худший случай спектакльO (п2) (наихудший из известных наихудший случай последовательности пробелов)
O (п бревно2п) (наиболее известная последовательность разрыва наихудшего случая)[1]
Лучший случай спектакльO (п бревно п) (большинство разрывов)
O (п бревно2п) (наиболее известная последовательность разрывов наихудшего случая)[2]
Средний спектакльзависит от последовательности разрыва
Худший случай космическая сложностьО (п) всего, O (1) вспомогательных
Шаги Shellsort.
Замена пар элементов на последовательных шагах Shellsort с пробелами 5, 3, 1

Shellsort, также известный как Сортировка оболочки или же Метод Шелл, является на месте сортировка сравнения. Его можно рассматривать как обобщение сортировки путем обмена (пузырьковая сортировка ) или сортировка вставкой (вставка сортировки ).[3] Метод начинается с сортировки пар элементов на большом расстоянии друг от друга, а затем постепенного уменьшения разрыва между сравниваемыми элементами. Начав с удаленных друг от друга элементов, он может перемещать некоторые неуместные элементы на место быстрее, чем простой обмен ближайшими соседями. Дональд Шелл опубликовал первую подобную версию в 1959 г.[4][5] Время работы Shellsort сильно зависит от используемой им последовательности пропусков. Для многих практических вариантов определение их временная сложность остается открытая проблема.

Описание

Shellsort - это оптимизация вставка сортировки что позволяет обмениваться предметами, находящимися далеко друг от друга. Идея состоит в том, чтобы организовать список элементов таким образом, чтобы начиная с любого места, каждый час-й элемент создает отсортированный список. Такой список называется час-сортировано. Его также можно рассматривать как час чередующиеся списки, каждый индивидуально отсортированный.[6] Начиная с больших значений час позволяет элементам перемещаться на большие расстояния в исходном списке, быстро уменьшая большое количество беспорядка и оставляя меньше работы для более мелких час-сортировать шаги, которые нужно сделать.[7] Если список то k-сортированный для некоторого меньшего целого k, то список остается час-сортировано. Следуя этой идее для убывающей последовательности час значения, заканчивающиеся на 1, гарантированно оставляют отсортированный список в конце.[6]

Проще говоря, это означает, что если у нас есть массив из 1024 чисел, наш первый пробел (час) может быть 512. Затем мы просматриваем список, сравнивая каждый элемент в первой половине с элементом во второй половине. Наш второй пробел (k) равно 256, что разбивает массив на четыре части (начиная с 0,256,512,768), и мы убеждаемся, что первые элементы в каждом разделе отсортированы относительно друг друга, затем второй элемент в каждом разделе и так далее. На практике последовательность пропусков может быть любой, но последний пробел всегда равен 1, чтобы завершить сортировку (фактически завершение обычной сортировки вставкой).

Пример выполнения Shellsort с пробелами 5, 3 и 1 показан ниже.

а1а2а3а4а5а6а7а8а9а10а11а12
Входные данные628318530717958647692528
После 5-сортировки172818470725838653696295
После 3-сортировки170718472825696253838695
После 1-сортировки071718252847536269838695

Первый проход, 5-сортировка, выполняет сортировку вставкой на пяти отдельных подмассивах (а1, а6, а11), (а2, а7, а12), (а3, а8), (а4, а9), (а5, а10). Например, он меняет подмассив (а1, а6, а11) с (62, 17, 25) на (17, 25, 62). Следующий проход, 3-сортировка, выполняет сортировку вставкой для трех подмассивов (а1, а4, а7, а10), (а2, а5, а8, а11), (а3, а6, а9, а12). Последний проход, 1-сортировка, представляет собой обычную сортировку вставкой всего массива (а1,..., а12).

Как показывает пример, подмассивы, с которыми работает Shellsort, изначально короткие; позже они стали длиннее, но почти заказаны. В обоих случаях сортировка вставкой работает эффективно.

Shellsort не стабильный: он может изменить относительный порядок элементов с равными значениями. Это алгоритм адаптивной сортировки в том, что он выполняется быстрее, когда ввод частично отсортирован.

Псевдокод

Использование последовательности пробелов Марцина Чиуры с внутренней сортировкой вставкой.

# Сортировать массив a [0 ... n-1].пробелы = [701, 301, 132, 57, 23, 10, 4, 1]# Начните с наибольшего разрыва и уменьшите его до 1для каждого (зазор в пробелы){    # Выполните сортировку вставки с зазором для этого размера зазора.    # Первые элементы пробела a [0..gap-1] уже находятся в порядке пробелов    # продолжайте добавлять еще один элемент, пока весь массив не будет отсортирован    за (я = зазор; я < п; я += 1)    {        # добавить [i] к элементам, которые были отсортированы по пробелам        # сохраняем [i] в ​​температуре и делаем дыру в позиции i        темп = а[я]        # сдвигаем ранее отсортированные по пробелам элементы вверх, пока не будет найдено правильное местоположение для [i]        за (j = я; j >= зазор и а[j - зазор] > темп; j -= зазор)        {            а[j] = а[j - зазор]        }        # поместите temp (исходный a [i]) в правильное место        а[j] = темп    }}

Последовательности пробелов

Вопрос о том, какую последовательность пробелов использовать, является трудным. Каждая последовательность пробелов, содержащая 1, дает правильную сортировку (так как это делает последний проход обычной сортировкой вставкой); однако свойства полученных таким образом версий Shellsort могут сильно отличаться. Слишком мало пропусков замедляет проходы, а слишком большое количество пропусков приводит к накладным расходам.

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

OEISОбщий термин (k ≥ 1)Бетонные зазорыХудший случай
временная сложность
Автор и год публикации
[например. когда N = 2п]Ракушка, 1959[4]
Фрэнк и Лазарь, 1960[8]
A000225Хиббард, 1963[9]
A083318, с префиксом 1Папернов и Стасевич, 1965 г.[10]
A003586Последовательные числа формы (3-гладкий числа)Пратт, 1971[1]
A003462, не более Knuth, 1973,[3] на основе Пратт, 1971[1]
A036569Incerpi & Sedgewick, 1985,[11] Knuth[3]
A036562, с префиксом 1Седжвик, 1982[6]
A033622Седжвик, 1986[12]
НеизвестноГонне & Баеза-Йейтс, 1991[13]
A108870НеизвестноТокуда, 1992 г.[14]
A102549Неизвестно (получено экспериментально)НеизвестноЧиура, 2001[15]

Когда двоичное представление N содержит много последовательных нулей, Shellsort с использованием исходной последовательности пробелов Shell делает Θ (N2) сравнения в худшем случае. Например, этот случай имеет место для N равняется степени двойки, когда элементы больше и меньше медианы занимают нечетные и четные позиции соответственно, поскольку они сравниваются только на последнем проходе.

Хотя он имеет более высокую сложность, чем О(N бревноN), оптимального для сравнительных сортировок, версия Пратта поддается сортировочные сети и имеет ту же асимптотическую сложность ворот, что и метод Батчера битонный сортировщик.

Гоннет и Баеза-Йейтс заметили, что Shellsort в среднем делает наименьшее количество сравнений, когда соотношение последовательных пропусков примерно равно 2,2.[13] Поэтому их последовательность с коэффициентом 2.2 и последовательность Токуды с коэффициентом 2.25 оказываются эффективными. Однако неизвестно, почему это так. Седжвик рекомендует использовать зазоры с низким наибольшие общие делители или попарно совмещать.[16]

Что касается среднего числа сравнений, последовательность Чиуры[15] имеет самую известную производительность; пробелы от 701 не определены, но последовательность может быть расширена в соответствии с рекурсивной формулой .

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

Вычислительная сложность

Имеет место следующее свойство: после час2-сортировка любых час1-сортированный массив, массив остается час1-сортировано.[17] Каждый час1-сортированные и час2-сортированный массив также (а1час1+а2час2) -сортировано для любых неотрицательных целых чисел а1 и а2. Таким образом, наихудшая сложность Shellsort связана с Проблема Фробениуса: для заданных целых чисел час1,..., часп при gcd = 1 число Фробениуса грамм(час1,..., часп) - наибольшее целое число, которое нельзя представить в виде а1час1+ ... +апчасп с неотрицательным целым числом а1,..., ап. Используя известные формулы для чисел Фробениуса, мы можем определить наихудшую сложность Shellsort для нескольких классов разрывных последовательностей.[18] Проверенные результаты показаны в таблице выше.

Что касается среднего количества операций, ни один из доказанных результатов не касается практической последовательности пропусков. Для пробелов, равных степени двойки, Эспелид вычислил это среднее как .[19] Knuth определила среднюю сложность сортировки N-элементный массив с двумя пробелами (час, 1) быть .[3] Отсюда следует, что двухпроходная сортировка Shellsort с час = Θ (N1/3) составляет в среднем О(N5/3) сравнения / инверсии / время работы. Яо нашли среднюю сложность трехпроходной сортировки Shellsort.[20] Его результат был уточнен Янсоном и Кнутом:[21] среднее количество сравнений / инверсий / время выполнения, сделанных во время Shellsort с тремя пробелами (ch, cg, 1), где час и грамм взаимно просты, является в первом проходе, во втором проходе и в третьем проходе. ψ(час, грамм) в последней формуле представляет собой сложную функцию, асимптотически равную . В частности, когда час = Θ (N7/15) и грамм = Θ (N1/5) среднее время сортировки О(N23/15).

На основании экспериментов предполагается, что Shellsort с Хиббард последовательность пробелов выполняется в О(N5/4) среднее время,[3] и что последовательность Гонне и Баеза-Йейтса требует в среднем 0,41NперN(ln lnN+1/6) элемент перемещается.[13] Приближение среднего числа операций, ранее выдвигавшихся для других последовательностей, не дает результата, если отсортированные массивы содержат миллионы элементов.

На графике ниже показано среднее количество сравнений элементов в различных вариантах Shellsort, разделенное на теоретическую нижнюю границу, т.е. log2N!, где последовательность 1, 4, 10, 23, 57, 132, 301, 701 была расширена по формуле .

Shell sort среднее количество сравнений (английский) .svg

Применяя теорию Колмогоровская сложность, Цзян, Ли, и Витани доказали следующую нижнюю оценку порядка среднего числа операций / времени работы в п-pass Shellsort: Ω (pN1+1/п) когда п≤log2N и Ω (pN) когда п> журнал2N.[22] Следовательно, Shellsort имеет перспективы работать в среднем за время, которое асимптотически растет как NбревноN только при использовании последовательностей пробелов, количество пробелов которых растет пропорционально логарифму размера массива. Однако неизвестно, сможет ли Shellsort достичь этого асимптотического порядка средней сложности, который является оптимальным для сортировок сравнения. Нижняя оценка была улучшена Витани[23] за каждое количество проходов к куда . Из этого результата следует, например, нижняя оценка Цзян-Ли-Витаньи для всех -pass последовательности приращений и улучшает эту нижнюю границу для определенных последовательностей приращений. Фактически все границы (нижняя и верхняя), известные в настоящее время для среднего случая, точно совпадают с этой нижней границей. Например, это дает новый результат: Янсон -Knuth верхняя граница совпадает с полученной нижней границей для используемой последовательности приращения, показывая, что трехпроходная сортировка Shellsort для этой последовательности приращения использует сравнения / инверсии / время выполнения. Формула позволяет нам искать последовательности приращений, которые дают неизвестные нижние границы; например, последовательность приращения для четырех проходов, нижняя граница которой превышает для последовательности приращения. Нижняя граница становится

Наихудшая сложность любой версии Shellsort имеет более высокий порядок: Plaxton, Poonen, и Suel показали, что он растет по крайней мере так же быстро, как .[24]

Приложения

Shellsort выполняет больше операций и имеет более высокую коэффициент промахов кэша чем быстрая сортировка. Однако, поскольку он может быть реализован с использованием небольшого количества кода и не использует стек вызовов, некоторые реализации qsort функция в Стандартная библиотека C нацелены на встроенные системы используйте его вместо быстрой сортировки. Shellsort, например, используется в uClibc библиотека.[25] По тем же причинам в прошлом Shellsort использовался в Ядро Linux.[26]

Shellsort также может служить под-алгоритмом интроспективная сортировка, чтобы отсортировать короткие подмассивы и предотвратить замедление, когда глубина рекурсии превышает заданный предел. Этот принцип используется, например, в bzip2 компрессор.[27]

Смотрите также

Рекомендации

  1. ^ а б c Пратт, Воан Рональд (1979). Shellsort and Sorting Networks (Выдающиеся диссертации в области компьютерных наук). Гирлянда. ISBN  978-0-8240-4406-0.
  2. ^ "Shellsort & Сравнение".
  3. ^ а б c d е Кнут, Дональд Э. (1997). «Метод Шелл». Искусство программирования. Том 3: Сортировка и поиск (2-е изд.). Ридинг, Массачусетс: Эддисон-Уэсли. С. 83–95. ISBN  978-0-201-89685-5.
  4. ^ а б Шелл, Д. Л. (1959). «Процедура высокоскоростной сортировки» (PDF). Коммуникации ACM. 2 (7): 30–32. Дои:10.1145/368370.368387.
  5. ^ В некоторых старых учебниках и справочниках это называется сортировкой «Шелл – Мецнер» после Марлен Мецнер Нортон, но, по словам Мецнера, «я не имел никакого отношения к этому сорту, и мое имя никогда не должно было быть связано с ним». Видеть «Шелл-сортировка». Национальный институт стандартов и технологий. Получено 17 июля 2007.
  6. ^ а б c Седжвик, Роберт (1998). Алгоритмы на C. 1 (3-е изд.). Эддисон-Уэсли. стр.273–281. ISBN  978-0-201-31452-6.
  7. ^ Керниган, Брайан В.; Ричи, Деннис М. (1996). Язык программирования C (2-е изд.). Прентис Холл. п. 62. ISBN  978-7-302-02412-5.
  8. ^ Франк, Р. М .; Лазарь, Р. Б. (1960). «Процедура высокоскоростной сортировки». Коммуникации ACM. 3 (1): 20–22. Дои:10.1145/366947.366957.
  9. ^ Хиббард, Томас Н. (1963). «Эмпирическое исследование минимальной сортировки памяти». Коммуникации ACM. 6 (5): 206–213. Дои:10.1145/366552.366557.
  10. ^ Папернов, А. А .; Стасевич, Г. В. (1965). «Метод сортировки информации в компьютерной памяти» (PDF). Проблемы передачи информации. 1 (3): 63–75.
  11. ^ Инчерпи, Джанет; Седжвик, Роберт (1985). «Улучшенные верхние границы для Shellsort» (PDF). Журнал компьютерных и системных наук. 31 (2): 210–224. Дои:10.1016 / 0022-0000 (85) 90042-х.
  12. ^ Седжвик, Роберт (1986). «Новая верхняя граница для Shellsort». Журнал алгоритмов. 7 (2): 159–173. Дои:10.1016/0196-6774(86)90001-5.
  13. ^ а б c Gonnet, Gaston H .; Баеза-Йейтс, Рикардо (1991). «Шеллсорт». Справочник по алгоритмам и структурам данных: на языках Pascal и C (2-е изд.). Ридинг, Массачусетс: Эддисон-Уэсли. С. 161–163. ISBN  978-0-201-41607-7.
  14. ^ Токуда, Наоюки (1992). «Улучшенная сортировка по шеллам». В ван Левен, Ян (ред.). Материалы 12-го Всемирного компьютерного конгресса IFIP по алгоритмам, программному обеспечению и архитектуре. Амстердам: Издательство Северной Голландии, стр. 449–457. ISBN  978-0-444-89747-3.
  15. ^ а б Чиура, Марцин (2001). «Лучшие приращения для среднего случая сортировки шелл» (PDF). У Фрейвальдов, русинов (ред.). Материалы 13-го Международного симпозиума по основам теории вычислений. Лондон: Springer-Verlag. С. 106–117. ISBN  978-3-540-42487-1.
  16. ^ Седжвик, Роберт (1998). «Шеллсорт». Алгоритмы в C ++, части 1–4: основы, структура данных, сортировка, поиск. Ридинг, Массачусетс: Эддисон-Уэсли. С. 285–292. ISBN  978-0-201-35088-3.
  17. ^ Гейл, Дэвид; Карп, Ричард М. (1972). «Феномен в теории сортировки». Журнал компьютерных и системных наук. 6 (2): 103–115. Дои:10.1016 / S0022-0000 (72) 80016-3.
  18. ^ Сельмер, Эрнст С. (1989). «О Шеллсорте и проблеме Фробениуса». BIT вычислительная математика. 29 (1): 37–40. Дои:10.1007 / BF01932703. HDL:1956/19572.
  19. ^ Эспелид, Терье О. (1973). «Анализ алгоритма сортировки шелл». BIT вычислительная математика. 13 (4): 394–400. Дои:10.1007 / BF01933401.
  20. ^ Яо, Эндрю Чи-Чи (1980). "Анализ (час, k, 1) -Сортировка ". Журнал алгоритмов. 1 (1): 14–50. Дои:10.1016/0196-6774(80)90003-6.
  21. ^ Янсон, Сванте; Кнут, Дональд Э. (1997). «Shellsort с тремя приращениями». Случайные структуры и алгоритмы. 10 (1–2): 125–142. arXiv:cs / 9608105. Дои:10.1002 / (SICI) 1098-2418 (199701/03) 10: 1/2 <125 :: AID-RSA6> 3.0.CO; 2-X. CiteSeerX: 10.1.1.54.9911.
  22. ^ Цзян, Дао; Ли, Мин; Витани, Пол (2000). «Нижняя граница усредненной сложности Shellsort». Журнал ACM. 47 (5): 905–911. arXiv:cs / 9906008. Дои:10.1145/355483.355488. CiteSeerX: 10.1.1.6.6508.
  23. ^ Витани, Пол (2018). «О средней сложности Shellsort». Случайные структуры и алгоритмы. 52 (2): 354–363. arXiv:cs / 9906008. Дои:10.1002 / rsa.20737.
  24. ^ Плэкстон, К. Грег; Пунен, Бьорн; Суэль, Торстен (1992). Улучшенные нижние границы для Shellsort. Ежегодный симпозиум по основам информатики. 33. С. 226–235. CiteSeerX  10.1.1.460.2429. Дои:10.1109 / SFCS.1992.267769. ISBN  978-0-8186-2900-6. CiteSeerX: 10.1.1.43.1393.
  25. ^ Новоа, Мануэль III. "libc / stdlib / stdlib.c". Получено 29 октября 2014.
  26. ^ "ядро / groups.c". Получено 5 мая 2012.
  27. ^ Джулиан Сьюард. "bzip2 / blocksort.c". Получено 30 марта 2011.

Библиография

внешняя ссылка