Сравнение между timsort и quicksort

Почему я в основном слышу о том, что quicksort является самым быстрым общим алгоритмом сортировки, когда timsort (согласно Википедии), кажется, работает намного лучше? Google, похоже, не нашел никакого сравнения.

5 ответов


TimSort - это высоко оптимизационный mergesort, он стабилен и быстрее, чем старый mergesort.

при сравнении с quicksort, он имеет два преимущества:

  1. Это невероятно быстро для почти отсортированной последовательности данных (включая обратные отсортированные данные);
  2. в худшем случае все еще O(N * LOG (N)).

честно говоря, я не думаю, что #1 является преимуществом, но это произвело на меня впечатление.

вот быстрая сортировка по преимущества

  1. QuickSort очень очень просто, даже очень настроенная реализация, мы можем записать свои коды pseduo в пределах 20 строк;
  2. QuickSort является самым быстрым в большинстве случаев;
  3. потребление памяти-LOG (N).

В настоящее время Java 7 SDK реализует timsort и новый вариант quicksort: т. е. двойной Pivot QuickSort.

Если вам нужна стабильная сортировка, попробуйте timsort, иначе начните с quicksort.


более или менее, это связано с тем, что Timsort - гибридный алгоритм сортировки. Это означает, что в то время как два базовых сорта, которые он использует (Mergesort и Insertion sort), оба хуже, чем Quicksort для многих видов данных Timsort использует их только тогда, когда это выгодно.

на немного более глубоком уровне, как Patrick87 состояния, quicksort является наихудшим случаем O (n2). Выбор хорошего pivot не жесткий, но гарантирование o (n log n) quicksort происходит за счет обычно более медленной сортировки в среднем.

для получения более подробной информации о Timsort см. ответ и связанный пост в блоге. Он в основном предполагает, что большинство данных уже частично отсортированы, и создает "запуски" отсортированных данных, которые позволяют эффективно объединять с помощью mergesort.


вообще говоря, quicksort-лучший алгоритм для примитивного массива. Это связано с памятью местности и кэша.

JDK7 использует TimSort для массива объектов. Массив объектов содержит только ссылку на объект. Сам объект хранится в куче. Чтобы сравнить объект, нам нужно прочитать объект из кучи. Это похоже на чтение из одной части кучи для одного объекта, а затем случайное чтение объекта из другой части кучи. Будет много пропусков. Я думаю по этой причине локальности памяти это уже не важно. Возможно, поэтому JDK использует TimSort только для массива объектов, если это примитивный массив.

Это только мое предположение.


вот контрольные номера с моей машины (i7-6700 CPU, 3.4 GHz, Ubuntu 16.04, gcc 5.4.0, параметры: SIZE=100000 и RUNS=3):

$ ./demo 
Running tests
stdlib qsort time:                 12246.33 us per iteration
##quick sort time:                  5822.00 us per iteration
merge sort time:                    8244.33 us per iteration
...    
##tim sort time:                    7695.33 us per iteration
in-place merge sort time:           6788.00 us per iteration    
sqrt sort time:                     7289.33 us per iteration    
...
grail sort dyn buffer sort time:    7856.67 us per iteration

бенчмарк исходит от Свенсона вроде проект в котором он как реализовал несколько алгоритмов сортировки в C. предположительно, его реализации достаточно хороши, чтобы быть представителем, но я не исследовал их.

Так что вы действительно не могу сказать. Контрольные номера остаются актуальными только для at почти два года, а потом приходится их повторять. Возможно, timsort обыграл qsort waaay еще в 2011 году, когда был задан вопрос, но времена изменились. Или qsort всегда был самым быстрым, но timsort победил его на неслучайных данных. Или код Свенсона не так хорошо и лучший программист мог бы переломить ситуацию в пользу timsort по. Или, возможно, я отстой и не использовал правильный CFLAGS при компиляции кода. Или... Вы получите точку.


Я не могу использовать стандартную сортировку java в соревнованиях по программированию codeforces, потому что java использует Double pivot quicksort для целых и двойных массивов, и поэтому существуют массивы, которые требуют O(n^2) времени для запуска. И некоторые тестовые данные часто состоят из этих массивов, поэтому программа занимает слишком много времени и терпит неудачу. Поэтому я должен переключиться на свой собственный mergeSort. Это не может произойти с алгоритмом timsort.