2010-01-28 3 views
1

У меня есть пара вопросов, касающихся различных вариантов сортировки вставки.InsertionSort против InsertionSort против BinaryInsertionSort

Осуществление 1:

public static void insertionSort(int[] a) { 
    for (int i = 1; i < a.length; ++i) { 
     int key = a[i]; 
     int j = i - 1; 

     while (j >= 0 && a[j] > key) { 
      a[j + 1] = a[j]; 
      --j; 
     } 

     a[j + 1] = key; 
    } 
} 

Осуществление 2:

public static void insertionSort(int[] a) { 
    for (int i = 1; i < a.length; ++i) { 
     for (int j = i; j > 0 && a[j - 1] > a[j]; --j) { 
      swap(a, j, j - 1); 
     } 
    } 
} 

private static void swap(int[] a, int i, int j) { 
    int tmp = a[i]; 

    a[i] = a[j]; 
    a[j] = tmp; 
} 

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

Во-вторых, мне было интересно, что метод Java Arrays.sort() также использует второй подход (возможно, из-за повторного использования кода, потому что метод подкачки используется в разных местах, возможно, потому, что это проще понять).

Реализация 3 (binaryInsertionSort):

public static void binaryInsertionSort(int[] a) { 
    for (int i = 1; i < a.length; ++i) { 
     int pos   = Arrays.binarySearch(a, 0, i, a[i]); 
     int insertionPoint = (pos >= 0) ? pos : -pos - 1; 

     if (insertionPoint < i) { 
      int key = a[i]; 

      // for (int j = i; i > insertionPoint; --i) { 
      //  a[j] = a[j - 1]; 
      // } 
      System.arraycopy(a, insertionPoint, a, insertionPoint + 1, i - insertionPoint); 

      a[insertionPoint] = key; 
     } 
    } 
} 

Является ли бинарная сортировка вставкой любого практического использования, или это скорее теоретическая вещь? На небольших массивах другие подходы намного быстрее, а на больших массивах mergesort/quicksort имеет намного лучшую производительность.

+1

Я бы предположил, что разница незначительна, потому что: для небольших массивов все время занимает пренебрежимо мало; для больших массивов время занимает доминирует производительность кэша. Так как дополнительные записи во второй версии смежны, записи, которые делают обе версии, вторая версия не требует доступа к дополнительным строкам кэша, поэтому производительность не влияет. Это только предположение, однако, даже возможно, что ваш JIT оптимизировал их, чтобы быть более или менее одинаковыми, и в равной степени я бы не удивился, если бы была разница в производительности. –

ответ

0
  1. удалить ложное утверждение
  2. количество сравнений в первых двух равна 1/2 * п (п-1), за исключением тех, для внешних контуров.
  3. Ни одна из этих программ не имеет большого смысла для реальной работы, поскольку они стоят, потому что они не используют информацию в их распоряжении. Например, легко добавить проверку во внутренний цикл, чтобы узнать, были ли сделаны какие-либо свопы: если нет, то массив сортируется, и вы можете закончить, возможно, сохранив большую часть работы. На практике эти виды рассмотрения могут доминировать в среднем случае.

Postscript пропущенный вопрос о Java: Я понимаю, что вроде Java является довольно сложный алгоритм, который использует много особых случаев, таких как специализированная сортировка случаев для небольших массивов, а также с помощью быстрой сортировки, чтобы сделать его тяжелая атлетика.

+0

Нет, первые два являются сортировками вставки (при условии, что они не являются багги). Сортировка вставки выполняет n - 1 проход, а после k проходит сортировка первых k + 1 элементов массива. В коде не может быть раннего выхода, потому что, например, последний элемент даже не посещается до последнего выполнения внешнего цикла. Сорт Bubble посещает весь массив на каждом проходе, но не полностью сортирует то, что он оставляет. –

+0

@Steve: Ой, да, по запросу вставка сортировка. Нет, re bubblesort - внутренний цикл обычно перенастраивает наибольшее или наименьшее значение и поэтому не нужно посещать весь массив при последующих проходах и может иметь такое же количество сравнений, как и наивная сортировка вставки. –

+0

Извините, вы правы, я упомянул только о посещении всего массива в качестве контраста с сортировкой вставки, чтобы показать, почему ранний выход отличается, а не оценивать время работы.Я должен был сказать: «сортировка пузырьков посещает весь массив на первом проходе», или «сортировка пузырьков посещает всю несортированную часть массива на каждом проходе» или некоторые такие. –