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

3.5. Рекурсия 141

Анализ Рекурсивных Алгоритмов, используя Следы Рекурсии

Мы можем проанализировать рекурсивный алгоритм при помощи визуального инструмента, известного как след рекурсии. Мы использовали следы рекурсии, например, чтобы проанализировать и визуализировать повторение - sive функция факториала Раздела 3.5, и мы так же используем следы рекурсии для рекурсивных алгоритмов сортировки Разделов 11.1 и 11.2.

Чтобы потянуть след рекурсии, мы создаем коробку для каждого случая функции и маркируем его параметрами функции. Кроме того, мы визуализируем рекурсивный вызов, таща стрелу из коробки функции запроса к коробке вызванной функции. Например, мы иллюстрируем след рекурсии алгоритма LinearSum Кодового Фрагмента 3.38 в рисунке 3.19. Мы маркируем, каждый окружает этот след с параметрами, используемыми, чтобы сделать этот звонок. Каждый раз, когда мы сделали рекурсивный звонок, мы чертим линию к коробке, представляющей рекурсивный вызов. Мы можем также использовать эту диаграмму, чтобы визуализировать продвижение через алгоритм, так как это проистекает, идя из требования

для n к призыву n- 1, к призыву n- 2, и так далее, полностью вниз к требованию

для 1. Когда заключительное требование заканчивается, оно возвращает свою стоимость назад к призыву 2, который

добавляет в его стоимости и возвращает эту частичную сумму к призыву 3, и так далее, до

призыв n- 1 прибыль его частичная сумма к призыву n.

Рисунок 3.19: след Рекурсии для выполнения LinearSum (A, n) с входом param-

эфиры =4, 3, 6, 2, 5 и n = 5.

От рисунка 3.19 должно быть ясно это для входного множества размера n, Алгоритма

LinearSum сделал n звонки. Следовательно, это занимает количество времени, которое является примерно propor-tional к n, так как это проводит постоянное количество времени, выполняющее нерекурсивную часть каждого требования. Кроме того, мы можем также видеть, что место в памяти, используемое алгоритмом (в дополнение ко множеству A), также примерно пропорционально n, так как нам нужно постоянное пространство объема памяти для каждого из n, окружает след в

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

время мы сделали заключительный рекурсивный звонок (для n = 1).

Изменение множества рекурсией

Затем, давайте рассмотрим проблему изменения n элементов множества, A, так, чтобы

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

время, которое мы называем этим алгоритмом, который мы делаем так как ReverseArray (A, 0, n- 1).

Алгоритм ReverseArray (A, я, j):

Вход: множество A и неотрицательная Продукция индексов i и j целого числа: аннулирование элементов в старте в индексе i и окончании в j, если я <j тогда

Обменяйтесь [я] и [j]

ReverseArray (A, я + 1, j- 1)

возвратиться

Кодовый Фрагмент 3.39: Изменение элементов множества, используя линейную рекурсию.

Обратите внимание на то, что в этом алгоритме у нас фактически есть два основных случая, а именно, когда я = j и когда i> j. Кроме того, или в случае, мы просто заканчиваем алгоритм, так как последовательность с нулевыми элементами или одним элементом тривиально равна его аннулированию. Кроме того, обратите внимание на то, что в рекурсивном шаге мы, как гарантируют, сделаем успехи к одному из этих двух основных случаев. Если n странный, мы в конечном счете достигаем меня = j случай, и если n даже, мы в конечном счете достигаем i> j случай. Вышеупомянутый аргумент immedi-ately подразумевает, что рекурсивный алгоритм Кодового Фрагмента 3.39, как гарантируют, закончится.

Определение проблем Способами, которые Облегчают Рекурсию

Чтобы проектировать рекурсивный алгоритм для данной проблемы, полезно думать о dif-

ferent путями, мы можем подразделить эту проблему определить проблемы, у которых есть та же самая общая структура как оригинальная проблема. Этот процесс иногда означает, что мы должны пересмотреть оригинальную проблему облегчить подобно выглядящие подпроблемы. Для экс-вполне достаточный, с алгоритмом ReverseArray, мы добавили параметры i и j так, чтобы у рекурсивного вызова полностью изменить внутреннюю часть множества A были та же самая структура (и тот же самый синтаксис) как требование полностью изменить все A. Затем вместо начального запроса

алгоритм как ReverseArray (A), мы называем его первоначально как ReverseArray (A, 0, n- 1).

В целом, если Вы испытываете затруднения при считании повторной структуры необходимой к дизайну a пере -

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