Что такое самый быстрый алгоритм сортировки для массива целых чисел?

55

Я сталкивался со многими алгоритмами сортировки во время учебы в старшей школе. Тем не менее, я никогда не знаю, какой самый быстрый (для случайного массива целых чисел). Итак, мои вопросы:

  • Какой самый быстрый в настоящее время известный алгоритм сортировки?
  • Теоретически, возможно, что есть еще более быстрые? Итак, какая наименьшая сложность для сортировки?
поколения
источник
7
Что вы подразумеваете под "быстро"? Что вы хотите измерить?
Рафаэль
2
Что означает «случайный массив целых чисел»? Случайно с каким распределением? равномерное распределение? Gaussian? В зависимости от распределения может быть лучше, чем алгоритмы ожидаемого времени выполнения. О(NжурналN)
Бакуриу
@gen Посмотрите на сортировку Radix. Корректная реализация имеет сложность O (n) для Int32, например.
это
Посмотрите на эталонный тест сортировки
adrianN
1
@gen: С точки зрения ; асимптотике? Тогда это легко: выберите любой из Θ ( n log n ) алгоритмов. Обратите внимание, что это может не иметь ничего общего с (средней) реальной производительностью. Это может быть стоит прочитать в этом отношении. ΘΘ(NжурналN)
Рафаэль

Ответы:

42

В общих чертах, существуют алгоритмы сортировки , такие как сортировка по вставкам, сортировка по пузырькам и сортировка по выбору, которые обычно следует использовать только в особых случаях; Быстрая сортировка, которая является наихудшим вариантом O ( n 2 ), но довольно часто O ( n log n ) с хорошими константами и свойствами и которая может использоваться в качестве процедуры сортировки общего назначения; О ( п войти п ) алгоритмы, как слияния сортировки и куча сортировку, которые также являются хорошими алгоритмами общего назначения сортировки; и О ( нО(N2)О(N2)О(NжурналN)О(NжурналN) , или линейные алгоритмы сортировки для списков целых чисел, таких как основание, ведро и счетные сортировки, которые могут быть подходящими в зависимости от природы целых чисел в ваших списках.О(N)

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

В более общем смысле, оптимальность алгоритма сортировки тесно связана с предположениями, которые вы можете сделать относительно типа списков, которые вы собираетесь сортировать (а также с моделью машины, на которой будет работать алгоритм, что может сделать даже плохую сортировку в противном случае). Алгоритмы лучший выбор, рассмотрите пузырьковую сортировку на машинах с лентой для хранения). Чем сильнее ваши предположения, тем больше углов может сократить ваш алгоритм. При очень слабых предположениях о том, насколько эффективно вы можете определить «сортировку» списка, оптимальной сложностью в худшем случае может быть даже .Ω(N!)

Этот ответ имеет дело только со сложностями. Фактическое время выполнения реализаций алгоритмов будет зависеть от большого числа факторов, которые трудно учесть в одном ответе.

Patrick87
источник
Я думаю, некоторые из этих должны быть Ω ? ОΩ
Рафаэль
1
@ Рафаэль Мех. Я думаю, что большинство из них или иначе. Я полагаю, что нижняя граница, вероятно, лучше отображается Ω . Я изменю пару из них, которые имеют смысл. ΘΩ
Patrick87
7
Я голосую @Raphael получает полицейскую шляпу : PΩ
Realz Slaw
2
@RealzSlaw: Я бы носил это с гордостью. :]
Рафаэль
1
@gen См. stackoverflow.com/a/3274203 для некоторого обсуждения. По сути, если отдельные записи огромны, и они не хранятся в режиме произвольного доступа, а объем данных таков, что их необходимо выполнять на месте, то пузырьковая сортировка - это путь. Эти обстоятельства обычно редки в наше время, но вы все равно можете столкнуться с ними.
Patrick87
16

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

На практике алгоритм сортировки в стандартной библиотеке вашего языка, вероятно, будет довольно хорошим (довольно близким к оптимальному), если вам нужна сортировка в памяти. Поэтому на практике просто используйте любую функцию сортировки, предоставляемую стандартной библиотекой, и измерьте время выполнения. Только если вы обнаружите, что (i) сортировка составляет большую часть общего времени выполнения, и (ii) время выполнения недопустимо, вы должны возиться с алгоритмом сортировки. Если эти два условия делают захват, то вы можете посмотреть на конкретных аспектах вашей конкретной области и эксперимента с другими быстро алгоритмами сортировки.

Но реально, на практике алгоритм сортировки редко является серьезным узким местом производительности.

DW
источник
9

Кроме того, отвечая на ваш второй вопрос

Теоретически, возможно, что есть еще более быстрые?
Итак, какая наименьшая сложность для сортировки?

Для сортировки общего назначения сложность задачи сортировки на основе сравнения составляет Ω (n log n) . Есть некоторые алгоритмы, которые выполняют сортировку в O (n), но все они основаны на предположениях относительно входных данных и не являются алгоритмами сортировки общего назначения.

По существу, сложность определяется минимальным количеством сравнений, необходимых для сортировки массива (log n представляет максимальную высоту двоичного дерева решений, построенного при сравнении каждого элемента массива).

Вы можете найти формальное доказательство для нижней границы сложности сортировки здесь :

rla4
источник
3
Этот ответ не совсем правильный. не является универсальной нижней границей для сортировки. Эта нижняя граница применяется только к сортировкам на основе сравнения , т. Е. К алгоритмам сортировки, которые используют только сравнения. Некоторые алгоритмы сортировки не основаны на сравнении. Утверждение «Есть некоторые алгоритмы, которые выполняют сортировку в O (n), но все они основаны на предположениях относительно входных данных, и не являются алгоритмами сортировки общего назначения». может быть немного вводит в заблуждение - будьте осторожны. Radix-sort - это алгоритм сортировки общего назначения (предполагается, что вы сортируете целые числа фиксированной ширины). Ω(nlogn)
DW
Зависит от того, что вы подразумеваете под проблемой сортировки . Сортировки общего назначения не являются единственными проблемами сортировки, которые возникают у людей.
Patrick87
1
Это правда, конечно. Я должен был быть более конкретным, спасибо за указание на это. Однако мне было немного любопытно, на какие другие подходы сортировки (не основанные на сравнении) вы ссылались; Radix Sort - это именно тот алгоритм O (n), о котором я говорил - вы должны «предположить» что-то о входных данных (целые числа фиксированной ширины). В этом смысле, это не универсальный алгоритм сортировки, верно?
rla4
1
@DW: сортировка по Radix не должна рассматриваться как алгоритм сортировки «общего назначения», так как для него требуются целочисленные ключи фиксированной длины; разве это не полезно в противном случае. Но я понимаю вашу точку зрения. :) Я предполагаю, что моей ошибкой было сосредоточение на сортировке чего-либо, что можно сравнить, а не на сортировке целых чисел , в частности. Это разные проблемы, и у них разный набор возможных решений. В вопросе упоминается «случайный массив целых чисел», но я признаю, что взял его в качестве примера, а не ограничения.
rla4
2
@DavidRicherby, оглядываясь назад через полтора года, я с тобой согласен. Спасибо.
DW
3

Самым быстрым алгоритмом целочисленной сортировки с точки зрения наихудшего случая, с которым я сталкивался, является Andersson et al. У него наихудший случай , что, конечно, быстрее, чем O ( n log n ) .О(NжурналжурналN)О(NжурналN)

user39994
источник
2
Это очень интересно, но вам нужно дать больше информации. Поскольку вы упоминаете , я предполагаю, что вы знаете, что сортировка общих целых чисел на основе сравнения доказуемо требует времени Ω ( n log n ) . Все, что асимптотически быстрее, чем это, должно делать предположения о данных: например, радикальная сортировка выполняется за линейное время, предполагая, что каждый элемент массива является не более некоторой постоянной. При каких условиях этот алгоритм сортирует по O ( n log log n ) и как он работает на практике с другими алгоритмами, такими как быстрая сортировка и сортировка по основанию? NжурналNΩ(NжурналN)О(NжурналжурналN)
Дэвид Ричерби
1

Я прочитал два других ответа во время написания этого, и я не думаю, что кто-то ответил на ваш вопрос должным образом. Другие ответы рассматривали посторонние идеи о случайных распределениях и сложности пространства, которые, вероятно, выходят за рамки изучения в старших классах. Итак, вот мое взятие.

AN(N-1)A(N-1)Ω(N)О(N)Ω(N)

Ω(N)О(N)N2N3N-51N2

bourbaki4481472
источник
О(N)NЛ.Г.NN232О(N)О(NЛ.Г.N)(для быстрой сортировки или сортировки слиянием) на практике сравнение не совсем понятно: константы, скрытые в нотации big-O, становятся очень важными, а константа для радикальной сортировки выше, чем константа для быстрой сортировки или слияния.
DW
lg(N)N
Ω(N)
2
O(wn)wwвес{0,...,2вес-1}журналNNвесзнак равножурналNNжурналN,
Дэвид Ричерби,
1

О(NLограммLограммN)
О(NLограммLограммU)U
дурак
источник
0

журнал(N!)

Ω(N)

Ив Дауст
источник
0

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

В теории, например, quick_sortесть O(n log n). С pпроцессорами в идеале это должно сводиться к тому, O(n/p log n)чтобы мы запускали его параллельно.

Процитирую Википедию: временная сложность ...

Оптимальная параллельная сортировка O (log n)

На практике для больших размеров входных данных это было бы невозможно достичь O(log n)из-за проблем с масштабируемостью.

Вот псевдокод для параллельной сортировки слиянием . Реализация merge()может быть такой же, как в обычной сортировке слиянием:

// Sort elements lo through hi (exclusive) of array A.
algorithm mergesort(A, lo, hi) is
    if lo+1 < hi then  // Two or more elements.
        mid = ⌊(lo + hi) / 2⌋
        fork mergesort(A, lo, mid)
        mergesort(A, mid, hi)
        join
        merge(A, lo, mid, hi)

Также см:

Kashyap
источник
О(N2)
@ Зло Да. Быстрая сортировка плохо подходит для параллельной обработки. Это пример. Те, которые должны быть использованы, перечислены в приведенных ссылках.
Кашьяп