размер стека быстрой сортировки

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

3 ответов


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

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

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

когда мы начинаем обрабатывать "большие части", каждая" большая часть "B(k) больше, чем" малая часть " S(k), произведенная в то же время, поэтому нам может понадобиться больше стека для обработки B(k), чем нам нужно для обработки S(k). Но B(k) все еще меньше, чем предыдущая "малая часть", S(k-1), и как только мы обрабатываем B (k),мы взяли его обратно из стека, поэтому является одним элементом меньше, чем при обработке S(k), и того же размера, что и при обработке S(k-1). Значит, мы все еще связаны.

предположим, что мы сделали это наоборот-толкнули маленькую часть и продолжили работу с большой частью. Тогда в патологически неприятном случае мы бы нажали размер 1 диапазон в стеке каждый раз и продолжить работу с размером только 2 меньше, чем предыдущий размер. Следовательно, нам нужно n / 2 слоты в нашем стеке.


рассмотрим наихудший случай, когда вы разделяете таким образом, что ваш раздел равен 1:n. Если вы сначала сортируете небольшой подфайл, вам нужно использовать только O (1) пространство, когда вы нажимаете большой подфайл, а затем возвращаете его (а затем снова нажимаете большой подфайл). Но, если вы сначала сортируете большой подфайл, чем вам нужно O (N) пространство, потому что вы продолжаете нажимать массив 1 элемента в стеке.

вот цитата из алгоритмов Роберта Седжвика (он был тем, кто написал статью об этом) :

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


хорошо, я прав, что вы имеете в виду, если мы сделаем алгоритм Quicksort нерекурсивным, вы должны использовать стек, где вы помещаете разделы в стек?

Если это так: алгоритм должен выделять для каждой переменной, которую он использует память. Таким образом, если вы запускаете два экземпляра параллельно, они выделяют двойной объем одного пространства памяти алгоритма...

теперь, в рекурсивной версии, вы запускаете новый экземпляр алгоритма (который должен выделять память), но экземпляр, который вызывает рекурсивный, не заканчивается, поэтому выделенная память необходима! - >фактически, мы начали, скажем, 10 рекурсивных экземпляров и нужна память 10 * X, где X-память, необходимая одному экземпляру.

теперь мы используем нерекурсивный алгоритм. Вы должны выделить необходимую память только один раз. Фактически, вспомогательные переменные используют только пространство одного экземпляра. Чтобы выполнить функцию алгоритма, мы должны сохранить уже сделанные разделы (или то, что мы еще не сделали). Фактически, мы помещаем его в стек и снимаем разделы, пока не сделаем последний шаг "рекурсии". Итак, представьте: вы даете алгоритму массив. Рекурсивный алгоритм должен выделить весь массив и некоторые вспомогательные переменные с каждым экземпляром (опять же: если глубина рекурсии равна 10, нам нужна память 10*X, где массиву нужно много). Нерекурсивный должен выделить массив, вспомогательные переменные только один раз, но ему нужен стек. Однако, в конце концов, вы не поставите так много частей в стек, что рекурсивному алгоритму потребуется меньше памяти из-за того, что нам не нужно снова выделять массив каждый раз/экземпляр.

надеюсь, я описал это так, чтобы вы могли понять это, но мой английский не очень хорош. :)