Это репост вопроса о cs.SE от Janoma . Полный кредит и портит ему или cs.SE.
В курсе стандартных алгоритмов нас учат, что быстрая сортировка в среднем составляет O (n log n), а в худшем случае O (n²). В то же время изучаются другие алгоритмы сортировки, в которых O (n log n) в худшем случае (например, mergesort и heapsort ) и даже линейное время в лучшем случае (например, сортировка пузырьков ), но с некоторыми дополнительными потребностями в памяти.
После быстрого взгляда на еще несколько времен выполнения, естественно сказать, что быстрая сортировка не должна быть такой же эффективной, как другие.
Кроме того, учтите, что на базовых курсах программирования студенты изучают, что рекурсия не очень хороша в целом, потому что она может использовать слишком много памяти и т. Д. Поэтому (и хотя это не реальный аргумент), это дает идею, что быстрая сортировка не может быть действительно хорошо, потому что это рекурсивный алгоритм.
Почему же тогда быстрая сортировка превосходит другие алгоритмы сортировки на практике? Связано ли это со структурой реальных данных ? Это связано с тем, как работает память в компьютерах? Я знаю, что некоторые воспоминания намного быстрее, чем другие, но я не знаю, является ли это реальной причиной этой нелогичной работы (по сравнению с теоретическими оценками).
источник
Ответы:
Я бы не согласился, что быстрая сортировка лучше, чем другие алгоритмы сортировки на практике.
Для большинства целей Timsort - гибрид сортировки слиянием и сортировкой вставок, который использует тот факт, что сортируемые данные часто начинаются почти отсортированными или отсортированными в обратном порядке.
Простейшая быстрая сортировка (без случайного поворота) рассматривает этот потенциально распространенный случай как O (N ^ 2) (сводится к O (N lg N) со случайными поворотами), тогда как TimSort может обрабатывать эти случаи в O (N).
Согласно этим тестам в C #, сравнивающим встроенную быструю сортировку с TimSort, Timsort значительно быстрее в большинстве отсортированных случаев и немного быстрее в случае случайных данных, а TimSort становится лучше, если функция сравнения особенно медленная. Я не повторял эти тесты и не удивлюсь, если бы быстрая сортировка немного превысила TimSort для некоторой комбинации случайных данных или если во встроенной сортировке C # (основанной на быстрой сортировке) есть что-то странное, что замедляет ее. Тем не менее, TimSort имеет явные преимущества, когда данные могут быть частично отсортированы, и примерно равна быстрой сортировке по скорости, когда данные не сортируются частично.
TimSort также имеет дополнительный бонус за стабильность, в отличие от быстрой сортировки. Единственный недостаток TimSort - использование O (N) по сравнению с O (lg N) в обычной (быстрой) реализации.
источник
Быстрая сортировка считается более быстрой, потому что коэффициент меньше, чем у любого другого известного алгоритма. Для этого нет причины или доказательства, просто не было найдено алгоритма с меньшим коэффициентом. Это правда, что другие алгоритмы также имеют O ( n log n ) времени, но в реальном мире коэффициент также важен.
Обратите внимание, что для небольшой вставки данных сортировка (та, которая считается O ( n 2 )) выполняется быстрее из-за природы математических функций. Это зависит от конкретных коэффициентов, которые варьируются от машины к машине. (В конце концов, в действительности выполняется только сборка.) Так что иногда я думаю, что гибрид быстрой сортировки и сортировки вставкой является самым быстрым на практике.
источник
Быстрая сортировка не превосходит все другие алгоритмы сортировки. Например, сортировка по куче снизу вверх ( Wegener 2002 ) превосходит быструю сортировку для разумных объемов данных, а также является алгоритмом на месте. Это также легко реализовать (по крайней мере, не сложнее, чем какой-то оптимизированный вариант быстрой сортировки).
Это просто не так хорошо известно, и вы не найдете его во многих учебниках, что может объяснить, почему он не так популярен, как быстрая сортировка.
источник
Вы не должны концентрироваться только на худшем случае и только на временной сложности. Это больше о среднем, чем о худшем, о времени и пространстве.
Quicksort:
Также имейте в виду, что нотация большого О не учитывает никаких констант, но на практике это имеет значение, если алгоритм работает в несколько раз быстрее. Θ ( n log n ) означает, что алгоритм выполняется в K n log ( n ), где K является константой. Quicksort является алгоритм сравнения сортировки с наименьшим K .
источник
Quicksort часто является хорошим выбором, поскольку он достаточно быстрый, достаточно быстрый и простой в реализации.
Если вы серьезно относитесь к быстрой сортировке больших объемов данных, то вам, вероятно, лучше с некоторыми вариациями в MergeSort. Это может быть сделано для использования преимуществ внешнего хранилища, может использовать несколько потоков или даже процессов, но они не являются тривиальными для кода.
источник
Реальная производительность алгоритмов зависит от платформы, языка, компилятора, внимания программиста к деталям реализации, конкретных усилий по оптимизации и так далее. Таким образом, «преимущество постоянного фактора» быстрой сортировки не очень четко определено - это субъективное суждение, основанное на доступных в настоящее время инструментах, и грубая оценка «эквивалентных усилий по внедрению» кем бы на самом деле не проводилось сравнительное исследование производительности. ,
Тем не менее, я считаю, что быстрая сортировка работает хорошо (для случайного ввода), потому что она проста, и потому что ее рекурсивная структура относительно дружественна кешу. С другой стороны, поскольку его наихудший случай легко вызвать, любое практическое использование быстрой сортировки должно быть более сложным, чем указывалось бы в описании учебника: таким образом, измененные версии, такие как интросорт.
Со временем, когда доминирующая платформа изменится, различные алгоритмы могут получить или потерять свое (плохо определенное) относительное преимущество. Обычное понимание относительной производительности может значительно отстать от этого сдвига, поэтому, если вы действительно не уверены, какой алгоритм лучше всего подходит для вашего приложения, вы должны реализовать оба и протестировать их.
источник