InsertionSort против InsertionSort против BinaryInsertionSort - PullRequest
1 голос
/ 28 января 2010

У меня есть пара вопросов относительно различных реализаций сортировки вставкой.

Реализация 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 () также использует второй подход (возможно, из-за повторного использования кода, потому что метод swap используется в разных местах, может быть, потому что его легче понять).

Реализация 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;
        }
    }
}

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

1 Ответ

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

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

...