Почему Java 6 Arrays # sort (Object []) изменяется с сортировки слиянием на сортировку вставок для небольших массивов? - PullRequest
22 голосов
/ 11 июля 2011

Реализация слияния Java 6 в Arrays.java использует сортировку вставкой, если длина массива меньше некоторого порогового значения.Это значение жестко запрограммировано в 7. Поскольку алгоритм является рекурсивным, это в конечном итоге происходит много раз для большого массива.Канонический алгоритм сортировки слиянием этого не делает, просто использует сортировку слиянием до тех пор, пока в списке не останется только 1 элемент.

Это оптимизация?Если так, как это должно помочь?И почему 7?Сортировка вставки (даже из <=7 вещей) значительно увеличивает количество сравнений, необходимых для сортировки большого массива, что увеличивает стоимость сортировки, когда compareTo() вызовы медленные.

array-size vs #-of-comparisons for different values of INSERTIONSORT_THRESHOLD

(ось x равна size of array, ось y равна # of comparisons, для различных значений INSERTIONSORT_THRESHOLD)

Ответы [ 3 ]

18 голосов
/ 11 июля 2011

Да, это намеренно. Хотя Big-O слияния меньше, чем у квадратичных сортировок, таких как сортировка вставкой, выполняемые операции более сложны и, следовательно, медленнее.

Рассмотрим сортировку массива длиной 8. Сортировка слиянием делает ~ 14 рекурсивных вызовов сама себе в дополнение к 7 операциям слияния. Каждый рекурсивный вызов вносит некоторые нетривиальные издержки во время выполнения. Каждая операция слияния включает цикл, в котором индексные переменные должны быть инициализированы, увеличены и сравнены, временные массивы должны быть скопированы и т. Д. В целом можно ожидать более 300 «простых» операций.

С другой стороны, сортировка вставок по своей природе проста и использует около 8 ^ 2 = 64 операций, что намного быстрее.

Думайте об этом так. Когда вы сортируете список из 10 чисел вручную, вы используете сортировку слиянием? Нет, потому что ваш мозг гораздо лучше справляется с такими простыми вещами, как вставка. Однако, если бы я дал вам год, чтобы отсортировать список из 100 000 чисел, вы, возможно, были бы более склонны к сортировке списка.

Что касается магического числа 7, оно эмпирически выведено как оптимальное.

РЕДАКТИРОВАТЬ: В стандартном виде вставки из 8 элементов в худшем случае получается ~ 36 сравнений. В канонической сортировке слиянием у вас есть ~ 24 сравнения. Добавление накладных расходов от вызовов методов и сложности операций, сортировка вставки должна быть быстрее. Кроме того, если вы посмотрите на средний случай, сортировка вставки будет производить гораздо меньше сравнений, чем 36.

4 голосов
/ 21 февраля 2013

Сортировка вставки - n (n-1) / 2, а сортировка слиянием - n * (log n с основанием 2).

Учитывая это -

  1. Для массива длины 5 => Сортировка вставки = 10 и сортировка слиянием - 11.609
  2. Для массива длины 6 => Сортировка вставки = 15 и сортировка слиянием - 15.509
  3. Для массива длины7 => Insetion sort = 21 и сортировка слиянием 19.651
  4. Для массива длины 8 => Insetion sort = 28 и сортировка слиянием 24

Из приведенных выше данных ясно,до длины 6 сортировка с добавлением выполняется быстрее, а после 7 сортировка слиянием эффективна.

Это объясняет, почему используется 7.

3 голосов
/ 11 июля 2011

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

...