9.2.3. Стек и рекурсия
9.2.3. Стек и рекурсия
В качестве примера изоморфизма, существующего между стеком и рекурсией, рассмотрим классическую задачу о Ханойской башне.
По легенде где-то далеко на востоке существует старинный храм. Обитающие в нем монахи заняты решением единственной задачи: перемещением дисков с одного шеста на другой с соблюдением определенных правил. Первоначально на первом шесте было 64 диска. Когда все диски будут перемещены, настанет конец света.
Попутно разоблачим миф. Похоже, что на самом деле эту задачу впервые сформулировал французский математик Эдуард Люка в 1883 году, и никаких истоков в восточной культуре она не имеет. Сам Люка называл ее «Ханойской башней».
Так что если вас пугает конец света, можете успокоиться. Да и в любом случае для перемещения 64 дисков потребуется 264-1 ходов. Небольшой расчет на калькуляторе покажет, что монахи будут заняты своим делом несколько миллионов лет.
Однако вернемся к правилам игры. (Сформулируем их, хотя эту загадку знал уже самый первый студент самого первого факультета информатики.) Имеется шест, на который надето несколько дисков; назовем его исходным. Мы хотим переместить все диски на целевой шест, используя еще один вспомогательный шест как место промежуточного хранения. Проблема в том, что за один ход можно перемещать только один диск; при этом нельзя класть больший диск на меньший.
В следующем примере приведено решение этой задачи с использованием стека. Мы ограничились тремя дисками, потому что для перемещения 64 компьютеру потребовались бы века.
def towers(list)
while !list.empty?
n, src, dst, aux = list.pop
if n == 1
puts "Перемещаем диск с #{src} на #{dst}"
else
list.push [n-1, aux, dst, src]
list.push [1, src, dst, aux]
list.push [n-1, src, aux, dst]
end
end
end
list = []
list.push([3, "a", "c", "b"])
towers(list)
Вот что напечатает эта программа:
Перемещаем диск с а на с
Перемещаем диск с а на b
Перемещаем диск с с на b
Перемещаем диск с а на с
Перемещаем диск с b на а
Перемещаем диск с b на с
Перемещаем диск с а на с
Конечно, классическое решение этой задачи рекурсивно. Но, как мы отмечали, тесная связь между обоими алгоритмами не должна вызывать удивления, так как для рекурсии применяется невидимый системный стек.
def towers(n, src, dst, aux)
if n==1
puts "Перемещаем диск с #{src} на #{dst}"
else
towers(n-1, src, aux, dst)
towers(1, src, dst, aux)
towers(n-1, aux, dst, src)
end
end
towers(3, "а", "с", "b")
Печатается точно такой же результат. Возможно, вам будет интересно знать, что «закомментарили» предложения, осуществляющие вывод, и сравнили время работы. Никому не говорите, но рекурсивное решение оказалось в два раза быстрее!
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКДанный текст является ознакомительным фрагментом.
Читайте также
3.2 Сетевой стек Windows NT
3.2 Сетевой стек Windows NT Разобраться в особенностях стека сетевого ввода-вывода Windows NT важно по нескольким причинам. Клиент Windows NT использует стек сетевого ввода-вывода для получения доступа к ресурсам, которые находятся под управлением сервера, а также для передачи данных.
Стек протоколов TCP/IP
Стек протоколов TCP/IP Стек протоколов TCP/IP является основным и единственным способом взаимодействия конечного компьютера с глобальной сетью Интернет, а также основным стеком взаимодействия с другими компьютерами сети. Именно поэтому было решено рассказать в этой главе и
19. Рекурсия
19. Рекурсия Функция является рекурсивной, когда во время обработки появляется ее повторный вызов непосредственно или косвенно, через цепочку вызовов других функций.Прямая (непосредственная) рекурсия – это вызов функции внутри тела этой функции.int a(){…..a()…..}Косвенная
2.1.4. Стек TCP/IP
2.1.4. Стек TCP/IP Физический и канальный уровни полностью реализуются сетевой картой или модемом (или другим устройством, выполняющим ту же функцию) и ее драйвером. Здесь действительно достигнута настолько полная абстракция, что программист обычно не задумывается о том,
3.13.7. Рекурсия в регулярных выражениях
3.13.7. Рекурсия в регулярных выражениях Возможность повторно обращаться к подвыражению позволяет создавать рекурсивные регулярные выражения. Например, данный код находит любое вложенное выражение с правильно расставленными скобками (спасибо Эндрю Джексону):str = "а *
Стек (Stack)
Стек (Stack) Любая последовательность, поддерживающая операции back, push_back и pop_back, может использоваться для модификации stack. В частности, могут использоваться vector, list и deque.template ‹class Container›class stack { friend bool operator==(const stack‹Container›& х, const stack‹Container›& y); friend bool operator‹(const
6.16. Стек
6.16. Стек В разделе 4.5 операции инкремента и декремента были проиллюстрированы на примере реализации абстракции стека. В общем случае стек является очень полезным механизмом для сохранения текущего состояния, если в разные моменты выполнения программы одновременно
7.5. Рекурсия
7.5. Рекурсия Функция, которая прямо или косвенно вызывает сама себя, называется рекурсивной. Например:int rgcd( int vl, int v2 ){if ( v2 != 0 )return rgcd( v2, vl%v2 );return vl;}Такая функция обязательно должна определять условие окончания, в противном случае рекурсия будет продолжаться бесконечно.
33.4. Рекурсия
33.4. Рекурсия Может ли сценарий рекурсивно вызывать себя самого? Да,
Рекурсия
Рекурсия Отсутствие в XSLT изменяемых переменных (оценим красоту этой тавтологии) как, впрочем, и многое другое, делает этот язык совершенно непохожим на многие классические языки программирования. В этом разделе мы опишем рекурсию [Кормен и др. 2000, Кнут 2000] — чрезвычайно
Класс стек
Класс стек Этот пример даст возможность ознакомиться с практическим использованием утверждений. В предыдущей лекции была дана схема параметризованного класса "стек" в форме:class STACK [G] feature... Объявление компонент:count, empty, full, put, remove, itemendРеализация появится ниже. До
Класс стек
Класс стек Поставляемый с утверждениями класс STACK был оставлен пока в схематичной форме (STACK1). Теперь на суд предстанет полная версия, включающая реализацию.Для написания эффективного класса необходимо задать реализацию. В качестве таковой выберем реализацию стека на
Лекция 12. Рекурсия
Лекция 12. Рекурсия Рекурсия. Стек. Создание собственного стека. Применение рекурсии. "Чтобы понять рекурсию, сначала необходимо понять рекурсию".Данное высказывание очень четко выражает суть рекурсии. Рекурсия является базовой концепцией программирования вообще, а не
Стек
Стек Стек – абстрактная структура данных, устроенная по принципу LIFO «последний вошел – первый вышел» (last in, first out – LIFO). Наглядно стек может быть представлен стопкой подносов в кафетерии. Например, если кто-то кладет поднос на вершину стопки, то этот поднос будет первым,
Рекурсия
Рекурсия И еще один важный вопрос, связанный с вызовом функций.Мы уже узнали, что функции могут вызывать другие функции, конечно, если те уже определены. Но функции могут также вызывать и сами себя. Такой прием программирования называется рекурсией и иногда бывает очень