Подтвердить что ты не робот

Почему QuickSort использует O (log (n)) дополнительное пространство?

Я реализовал ниже алгоритм быстрой сортировки. Интернет Я читал, что у него есть потребность в пространстве O (log (n)). Почему это так? Я не создаю никаких дополнительных структур данных.

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

private static void quickSort (int[] array, int left, int right) {
    int index = partition(array, left, right);

    //Sort left half
    if (left < index - 1)
        quickSort(array, left, index - 1);

    //Sort right half
    if (index < right)
        quickSort(array, index , right);
}

private static int partition (int array[], int left, int right) {
    int pivot = array[(left + right) / 2]; //Pick pivot point
    while (left <= right) {
        //Find element on left that should be on right
        while (array[left] < pivot)
            left++;

        //Find element on right that should be on left
        while (array[right] > pivot)
            right--;

        //Swap elements and move left and right indices
        if (left <= right) {
            int temp = array[left];
            array[left] = array[right];
            array[right] = temp;
            left++;
            right--;
        }
    }
    return left;
}
4b9b3361

Ответ 1

Исправить, дополнительное пространство - это фреймы кадров журнала (n). Из статьи Википедии Quicksort:

Существует более сложная версия, в которой используется отдельный раздел алгоритм и может достичь полной сортировки с использованием пространства O (log n) (не подсчет ввода) в среднем (для стека вызовов).

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

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

Ответ 2

Чтобы избавиться от рекурсивного вызова, вам придется использовать стек в вашем коде, и он все равно будет занимать пробел log(n).

Ответ 3

Если вы читаете далее в статье в Википедии, вы найдете более подробное обсуждение сложности пространства. В частности, они пишут:

Quicksort с локальным и нестабильным разделением использует только постоянное дополнительное пространство перед выполнением любого рекурсивного вызова. Quicksort должен хранить постоянный объем информации для каждого вложенного рекурсивного вызова. Поскольку лучший случай делает не более O (log n) вложенных рекурсивных вызовов, он использует O (log n). Однако без использования Sedgewick для ограничения рекурсивных вызовов в худшем случае quicksort может сделать O (n) вложенные рекурсивные вызовы и O (n) вспомогательное пространство.

Практически говоря, O (log n) память ничего. Например, если вам нужно сортировать 1 миллиард ints, для их хранения потребуется 4 ГБ, но для стека потребуется всего около 30 кадров стека, например, 40 байтов, а значит, около 1200 байт.

Ответ 4

Да, это из-за кадров стека, и да, может быть возможно преобразовать его в итеративный алгоритм, делая что-то очень умное (хотя ничто не приходит сразу ко мне). Но почему? O (log (n)) - почти ничего. Для справки, даже если у вас есть массив максимального размера, разрешенный Java, это 2 ^ 31 элемента, что составляет около 8 ГБ. Для Quicksort потребуется 31 стек кадров. Баллпарк, может быть, 100 байт за кадр? Итак, всего 3 КБ, что ничто по сравнению с памятью для фактического массива.

В действительности, почти в любое время что-то есть O (log (n)), он почти такой же, как и константа.

Ответ 5

Извините за возрождение этого старого вопроса, но я просто нашел совершенно другой (но немного глупый) ответ на ваш вопрос, planetmath.org

Любой алгоритм сортировки, который работает с непрерывным массивом, требует дополнительного пространства O⁢ (log ⁡n), так как это число укуса [sic], необходимое для представления индекса в массив.