Я постараюсь дать более общий ответ в дополнение к фактическим реализациям, приведенным в других постах.
Возможно ли это, и если да, то как?
Давайте сначала посмотрим, что можно понять, создав рекурсивный алгоритм итеративный .
Например, мы хотим иметь некоторую функцию sum(n)
, которая суммирует числа от 0 до n
.
Конечно, это
sum(n) =
if n = 0
then return 0
else return n + sum(n - 1)
Когда мы попытаемся вычислить что-то вроде sum(100000)
, мы скоро увидим, что у этого рекурсивного алгоритма есть свои ограничения - произойдет переполнение стека.
Итак, в качестве решения мы используем итерационный алгоритм для решения той же проблемы.
sum(n) =
s <- 0
for i in 0..n do
s <- s + i
return s
Однако важно отметить, что эта реализация является совершенно другим алгоритмом, чем приведенная выше рекурсивная сумма. Мы каким-то образом не модифицировали исходный для получения итеративной версии, мы просто нашли нерекурсивный алгоритм - с другими и, возможно, лучшими характеристиками производительности - который решает ту же проблему.
Это первый аспект создания итеративного алгоритма: поиск другого итеративного алгоритма, который решает ту же проблему.
В некоторых случаях такой итеративной версии может просто не быть.
второй однако применим к каждому рекурсивному алгоритму . Вы можете превратить любую рекурсию в итерацию путем явного представления стека, который рекурсия использует неявно . Теперь этот алгоритм будет иметь те же характеристики, что и исходный, - и стек будет расти с O(n)
, как в рекурсивной версии. Это не так легко переполнится, поскольку он использует обычную память вместо стека вызовов и итеративный, но это все тот же алгоритм.
Что касается быстрой сортировки: не существует другой формулировки, которая работает без хранения данных, необходимых для рекурсии. Но, конечно, вы можете использовать для них явный стек, как показал Эхсан. Таким образом, вы можете - как всегда - создать итерационную версию.