Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Data Structures and Algorithms in C++ 2e (На ру...docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
2.37 Mб
Скачать

3.5. Рекурсия 147

3.5.3 Многократная рекурсия

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

горшок + кастрюля = пьет собаку + кошка = мальчик свиньи + девочка = ребенок

Чтобы решить такую загадку, мы должны назначить уникальную цифру (то есть, 0, 1..., 9) к каждому письму в уравнении, чтобы сделать уравнение верным. Как правило, мы решаем такую загадку при помощи наших человеческих наблюдений за особой загадкой, которую мы пытаемся решить, чтобы устранить конфигурации (то есть, возможные частичные назначения цифр к письмам), пока мы не можем работать, хотя выполнимые конфигурации уехали, проверив на правильность каждого.

Если число возможных конфигураций не слишком большое, однако, мы можем использовать компьютер, чтобы просто перечислить все возможности и проверить каждого, не используя человеческих наблюдений. Кроме того, такой алгоритм может использовать многократную рекурсию, чтобы работать через конфигурации систематическим способом. Мы показываем псевдо - кодируют для такого алгоритма в Кодовом Фрагменте 3.44. Чтобы сохранять описание достаточно общим, чтобы использоваться с другими загадками, алгоритм перечисляет и проверяет все k-последовательности длины без повторений элементов даваемого U набора. Мы строим последовательности k элементов следующими шагами:

1. Рекурсивно производя последовательности k- 1 элемент

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

В течение выполнения алгоритма мы используем набор U, чтобы отслеживать элементы, не содержавшиеся в текущей последовательности, так, чтобы элемент e еще не использовался, если и только если e находится в U.

Другой способ смотреть на алгоритм Кодового Фрагмента 3.44 состоит в том, что это enumer-ates каждый возможный размер-k, заказанный подмножество U, и, проверяет каждое подмножество на то, что оно было возможным решением нашей загадки.

Для загадок суммирования, U =0, 1, 2, 3, 4, 5, 6, 7, 8, 9 и каждое положение в

последовательность соответствует данному письму. Например, первое положение могло стоять

для b, второго для o, третьего для y, и так далее.

148 Глава 3. Множества, связанные списки и рекурсия

Алгоритм PuzzleSolve (k, S, U):

Вход: целое число k, последовательность S и набор U Продукция: перечисление всех расширений k-длины к S использование элементов в U

без повторений

поскольку каждый e в U делает

Удалите e из Ue, теперь используется

Добавьте e до конца S

если k = 1 тогда

Тест, является ли S конфигурацией, которая решает загадку, если S решает загадку тогда

возвратите «Найденное решение»: S еще

PuzzleSolve (k- 1, S, U)

Добавьте, что e назад к Ue теперь не использован

Удалите e из конца S

Кодовый Фрагмент 3.44: Решение комбинаторной загадки, перечисляя и проверяя все возможные конфигурации.

В рисунке 3.21 мы показываем след рекурсии звонка в PuzzleSolve (3, S, U),

где S пуст и U =a, b, c. Во время выполнения, всех перестановок

из этих трех знаков произведены и проверены. Обратите внимание на то, что начальное требование делает

три рекурсивных вызова, каждый из которых в свою очередь делает еще два. Если бы мы выполнили PuzzleSolve (3, S, U) на наборе U состоящий из четырех элементов, то начальное требование сделает четыре рекурсивных звонка, у каждого из которых был бы след, бывший похожий на тот в рисунке 3.21.

Рисунок 3.21: след Рекурсии для выполнения PuzzleSolve (3, S, U), где S

пустой и U =a, b, c. Это выполнение производит и проверяет все перестановки a, b,

и c. Мы показываем перестановки, произведенные непосредственно ниже их соответствующих коробок.