Рекурсия против циклов

Я пытаюсь работать с примерами деревьев, приведенными здесь: http://cslibrary.stanford.edu/110/BinaryTrees.html Все эти примеры решают проблемы с помощью рекурсии. Мне интересно, можем ли мы предоставить итеративное решение для каждой из них, то есть всегда ли мы уверены, что проблема, которую можно решить с помощью рекурсии, будет также есть итеративное решение, в общем. Если нет, то какой пример мы можем привести, чтобы показать проблему, которую можно решить только рекурсией / итерацией?

--


person sachin    schedule 17.04.2010    source источник


Ответы (6)


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

person Ben Voigt    schedule 17.04.2010
comment
Это интересная (и я считаю, правильная) формулировка. +1 - person Josh K; 18.04.2010
comment
кроме случаев переполнения встроенного стека. Тогда итеративная версия будет работать, а рекурсивная выйдет из строя. - person mmr; 18.04.2010
comment
@mmr: Ну, проще изменить размер определяемого пользователем стека, чем встроенный стек потоков в многокомпонентной среде (где изменение размера вашего стека может мешать работе других компонентов). А рекурсия обычно хранит в стеке немного больше данных (адрес возврата, а также локальное состояние). Но в целом оба масштабируются одинаково с точки зрения использования стека. Алгоритмы без поиска с возвратом могут быть закодированы итеративно без стека или с использованием хвостовой рекурсии, оба являются O (1). При возврате big-O будет одинаковым для обоих. - person Ben Voigt; 18.04.2010
comment
это теория. Теперь попробуйте рекурсивно пройтись по каждому элементу в блоке объемных данных размером 1024x1024x512 и посмотреть, как ваш стек взорвется. - person mmr; 18.04.2010
comment
Это количество состояния, которое необходимо поддерживать для отслеживания с возвратом, которое контролирует использование стека. Нет возврата? Хвостовая рекурсия - ›рост стека отсутствует. Много государства? В итеративном случае также потребуются гигабайты памяти. - person Ben Voigt; 18.04.2010

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

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

person Oded    schedule 17.04.2010
comment
Теоретически все рекурсивные решения могут быть переписаны итеративно. На практике вы в конечном итоге создаете и поддерживаете фрейм стека для многих из них. - person Chris Lutz; 18.04.2010
comment
мы всегда можем быть уверены? Я пытаюсь найти более формальное доказательство, но пока безуспешно ... Было бы действительно полезно знать, когда нам следует изо всех сил пытаться найти решение, а когда не следует ... - person sachin; 18.04.2010
comment
@sachin: Вы можете быть уверены, потому что вся рекурсия итеративна, она просто включает накладные расходы на поддержание информации о состоянии (то есть стека). - person Adam Robinson; 18.04.2010

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

Прочтите этот вопрос для подтверждения.

person IVlad    schedule 17.04.2010

Рекурсия и итерация - это два инструмента, которые на очень фундаментальном уровне делают одно и то же: выполняют повторяющуюся операцию над определенным набором значений. Они взаимозаменяемы в том смысле, что нет проблемы, которую нельзя было бы каким-либо способом решить только одним из них. Однако это не означает, что один не может быть более подходящим, чем другой.

person Adam Robinson    schedule 17.04.2010

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

Вы не можете создавать дополнительные циклы, но можете создавать новые потоки с помощью рекурсии.

person Josh K    schedule 17.04.2010
comment
Не правда. Обычный цикл while может продолжаться без известного конца. Фактически, быструю сортировку можно записать в итеративной форме, где рекурсия заменяется стеком. - person el.pescado; 18.04.2010

Как «старичок», я вспоминаю, что узнал, что парсеры с рекурсивным спуском легче писать, но что основанные на стеке итеративные парсеры работают лучше. Вот статья, которая, кажется, поддерживает эту идею с помощью показателей:

http://www.texttoolkit.com/index.php?option=com_content&view=article&catid=35%3Atechnology&id=60%3Abeyond-recursive-descent&Itemid=55

Следует отметить упоминание автором переполнения стека вызовов рекурсивным спуском. Итеративная реализация на основе стека может быть намного эффективнее с точки зрения ресурсов.

person BJ Safdie    schedule 17.04.2010