Комбинация Quicksort/Insertion Sort медленнее, чем просто Quicksort?

Я запускаю Quicksort 10 раз и получаю среднее среднее время. Я делаю то же самое для комбинации быстрой сортировки и сортировки вставками, и она кажется медленнее, чем простая быстрая сортировка.

Вот часть кода, где я вызываю InsertionSort

public static <T extends Comparable<? super T>> void OptQSort2 (T[] data, int min, int max) {
        int indexofpartition;
        if(max - min > 0) {
            if( (max - min) <= 10) {
                // Use InsertionSort now
                InsertionSort.sort(data);
                return;
            } else {
                indexofpartition = findPartition(data, min, max);

                OptQSort2(data, min, indexofpartition - 1);

                OptQSort2(data, indexofpartition + 1, max);
            }
        }

}

И обычная быстрая сортировка точно такая же, как приведенный выше фрагмент, но без условия if, которое вызывает InsertionSort.

FindPartition выглядит следующим образом:

public static <T extends Comparable<? super T>> int findPartition(T[] data, int min, int max) {
    int left, right;
    T temp, partitionelement;
    int middle = (min + max)/2;

    partitionelement = data[middle];
    left = min;
    right = max;

    while(left < right) {
        while(data[left].compareTo(partitionelement) <= 0 && left < right)
            left++;

        while(data[right].compareTo(partitionelement) > 0)
            right--;

        if(left < right) {
            temp = data[left];
            data[left] = data[right];
            data[right] = temp;
        }
    }

Среднее время только для Quicksort и OptSort2 (который использует сортировку вставками) составляет

Sorted using QuickSort in: 3858841
Sorted using OptQSort2 in: 34359610

Есть идеи, почему? Имеет ли значение размер последовательности? Я использую для этого массив из 1000 элементов Integer[]


person sqram    schedule 04.12.2011    source источник
comment
Является ли InsertionSort.sort() императивным рекурсивным порядком?   -  person Fabian Barney    schedule 05.12.2011
comment
не видя реализации QucikSort и InsertionSort невозможно сказать.   -  person Karoly Horvath    schedule 05.12.2011
comment
Это огромное и неожиданное несоответствие. Что именно делает InsertionSort.sort?   -  person Tom Anderson    schedule 05.12.2011


Ответы (4)


В OptQSort2 для небольших разделов у вас есть следующий вызов функции:

InsertionSort.sort(data);

Предполагается ли, что вставка сортирует небольшой раздел? Похоже, вы сортируете вставками весь массив. Разве вы не должны передавать индексы min и max в InsertionSort?

Другой вариант — просто не работать с небольшими разделами во время OptQSort2. Затем выполните один проход InsertionSort по всему массиву после того, как OptQSort2 выполнит свою работу.

person Blastfurnace    schedule 04.12.2011

Вам понадобится гораздо больший целочисленный массив, чтобы тест был релевантным. В этот момент, вероятно, проверка условия if замедлит работу вашего алгоритма в случае QS+IS.

Тестируйте на большое количество чисел и переключайтесь на IS, когда размер данных достаточен для размещения в кеше L1, т.е. 32-64 КБ.

person Tudor    schedule 04.12.2011
comment
один дополнительный if делает его в 10 раз медленнее? ты, должно быть, шутишь. - person Karoly Horvath; 05.12.2011
comment
Да, это должно быть что-то очень маленькое, иначе числа слишком велики для сортировки 1000 целых чисел. - person Tudor; 05.12.2011
comment
Выбор единицы не может повлиять на отношение, если только единица не слишком мала. - person user207421; 05.12.2011
comment
Это зависит от относительного времени сортировки и оценки if. Первое зависит от входа, второе постоянно. Он сказал, что сортирует 1000 целых чисел, что должно занять очень мало времени. В этом случае наличие оператора if оказывает большее влияние на общий расчет. - person Tudor; 05.12.2011

Первым подозреваемым, очевидно, является ваш метод сортировки вставками. Например, это действительно сортирует?

Вам также нужно будет протестировать его более 10 раз, чтобы разогреть JVM. А также проверить их в обоих порядках, чтобы один не выиграл от разогрева, выполненного другим. Я бы предложил 100 или 1000 тестов. И все они должны быть в одном наборе данных.

person user207421    schedule 04.12.2011

Вы не должны вызывать InsertionSort каждый раз, когда у вас есть подмассив не более чем из 10 элементов. Ничего не делайте:

public static <T extends Comparable<? super T>> void OptQSort2 (T[] data, int min, int max) {
    int indexofpartition;
        if( (max - min) > 10) {
            indexofpartition = findPartition(data, min, max);

            OptQSort2(data, min, indexofpartition - 1);

            OptQSort2(data, indexofpartition + 1, max);
        }

}

Когда вы закончите, вызовите InsertionSort для всего массива.

person Jon    schedule 05.03.2014