Важно иметь в виду, что существует множество различных способов реализации каждого из этих алгоритмов, и каждая отдельная реализация имеет различную связанную пространственную сложность.
Начнем с сортировки слиянием. Наиболее распространенная реализация сортировки слиянием для массивов работает путем выделения внешнего буфера, в котором выполняется слияние отдельных диапазонов. Это требует места для хранения всех элементов массива, что занимает дополнительное пространство (n). Однако в качестве альтернативы вы можете использовать слияние на месте для каждого слияния, что означает, что единственное дополнительное пространство, которое вам понадобится, будет пространством для кадров стека рекурсивных вызовов, снизив сложность пространства до (log n), но увеличение времени выполнения алгоритма в большой постоянный множитель. В качестве альтернативы вы можете выполнить сортировку слиянием снизу вверх, используя слияние на месте, которое требует всего O (1) дополнительного пространства, но с более высоким постоянным коэффициентом.
С другой стороны, если вы сортируете связанные списки слиянием, то сложность пространства будет совсем другой. Вы можете объединять связанные списки в пространстве O(1), потому что сами элементы можно легко перемонтировать. Это означает, что пространственная сложность связанных списков с сортировкой слиянием составляет (log n) от пространства, необходимого для хранения кадров стека для рекурсивных вызовов.
Давайте рассмотрим быструю сортировку в качестве другого примера. Быстрая сортировка обычно не выделяет никакой внешней памяти, но ей нужно место для используемых кадров стека. Наивной реализации быстрой сортировки может потребоваться пространство (n) в худшем случае для кадров стека, если опорные точки всегда оказываются наибольшим или наименьшим элементом массива, поскольку в этом случае вы продолжаете рекурсивно вызывать функцию для массивов размера n - 1, n - 2, n - 3 и т. д. Однако есть стандартная оптимизация, которую вы можете выполнить, по сути, исключающую хвостовой вызов: вы рекурсивно вызываете быструю сортировку на меньшей из двух половин массива, затем повторно используете пространство стека из текущий вызов для большей половины. Это означает, что вы выделяете новую память только для рекурсивного вызова подмассивов размером не более n/2, затем n/4, затем n/8 и т. д., поэтому использование пространства падает до O(log n).
person
templatetypedef
schedule
01.04.2016