Быстрая сортировка медленнее, чем Mergesort? - PullRequest
20 голосов
/ 31 января 2009

Вчера я работал над реализацией быстрой сортировки, а затем запустил ее, ожидая более быстрого выполнения, чем Mergesort (который я также реализовал). Я запустил два, и хотя быстрая сортировка была быстрее для небольших наборов данных <100 элементов (и я <i>проверил, что проверил, что это работает), сортировка слиянием стала более быстрым алгоритмом довольно быстро. Меня учили, что быстрая сортировка почти всегда «быстрее», чем сортировка слиянием, и я понимаю, что есть некоторые дебаты по этой теме, но я по крайней мере ожидал, что она будет ближе, чем эта. Для наборов данных> 10000 элементов сортировка слиянием была более чем в 4 раза быстрее. Это следовало ожидать, или в моем коде быстрой сортировки есть ошибка?

слияние:

public static void mergeSort(int[ ] e)
{
    if (e.length <= 1) return;
    int[] first = new int[e.length/2];
    int[] second = new int[e.length - first.length];
    System.arraycopy(e, 0, first, 0, first.length);
    System.arraycopy(e, first.length, second, 0, second.length);
    mergeSort(first);
    mergeSort(second);
    System.arraycopy(merge(first, second), 0, e, 0, e.length);
}

private static int[] merge(int[] first, int[] second) {
    int iFirst = 0;
    int iSecond = 0;
    int iCombined = 0;

    int[] combined = new int[first.length + second.length];
    while(iFirst < first.length && iSecond < second.length) {
        if (first[iFirst] > second[iSecond]) {
            combined[iCombined++] = second[iSecond++];
        }
        else combined[iCombined++] = first[iFirst++];
    }
    for(; iFirst < first.length; iFirst++) {
        combined[iCombined++] = first[iFirst];
    }
    for(; iSecond < second.length; iSecond++) {
        combined[iCombined++] = second[iSecond];
    }
    return combined;
}

быстрая сортировка:

public static void quicksort(int[] a, int first, int last) {
    if (first >= last) return;

    int partitionIndex = partition(a, first, last);
    quicksort(a, first, partitionIndex - 1);
    quicksort(a, partitionIndex + 1, last);
}

public static int partition(int[] x, int first, int last) {
    int left = first;
    int right = last;
    int pivot = x[first];
    int pivotIdx = first;

    while(left <= right) {
        while(left < x.length && x[left] <= pivot) left++;
        while(right >= 0 && x[right] > pivot) right--;
        if (left <= right) {
            int temp = x[left];
            x[left] = x[right];
            x[right] = temp;
        }
    }
    pivotIdx = right;
    x[first] = x[right];
    x[pivotIdx] = pivot;
    return pivotIdx;
}

Ответы [ 15 ]

1 голос
/ 31 января 2009

(1) Существует алгоритм qsort, используемый C qsort (), который не требует дополнительной памяти. это был наиболее вероятно изобретен Hoare. Это делает qsort () быстрым в C.

(2) Рандомизация данных перед запуском qsort почти всегда ускоряет их.

(3) выбор медианных данных для пивота может сделать его быстрее,

1 голос
/ 31 января 2009

Я мог бы представить, что с помощью прямого доступа к памяти, например, с помощью C, можно повысить производительность Quicksort больше, чем это возможно с Mergesort.

Другая причина заключается в том, что Mergesort требуется больше памяти, поскольку ее трудно реализовать как сортировку на месте.

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

Как видно из в википедии , Quicksort можно реализовать различными способами.

0 голосов
/ 31 января 2009

Для хорошей производительности быстрой сортировки важно не повторяться до списков длиной 1

Вы должны рассмотреть сортировку списков из 2, 3 и даже 4 как вложенных, если обмен местами при необходимости. Дайте нам знать, как меняется производительность.

0 голосов
/ 31 января 2009

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

0 голосов
/ 31 января 2009

Вы были достаточно случайными? Были ли они частично отсортированы?

Это может повлиять на скорость сортировки ...

Как и в случае раздела QuickSort (), вы будете пропускать, если числа расположены в отсортированном порядке, пока не найдете тот, который не соответствует.

...