Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции по информатике все.doc
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
986.62 Кб
Скачать

Применение бинарных деревьев

Бинарные деревья используются как структура данных тогда, когда в каждой точке процесса должно быть принято одно из двух возможных решений. Они применяются для синтаксического анализа, поиска, сортировки, управления базами данных и в других приложениях. Рассмотрим задачу определения дубликатов в списке целых чисел. Известный способ решения предлагает сравнивать каждое число со всеми предшествующими. Попробуем уменьшить число возможных сравнений, построив бинарное дерево по следующему принципу. Первое число из списка поместим в корень дерева. Каждое новое число будем сравнивать с числом в корне. Если оно меньше числа в корне, то перейдем в левое поддерево, иначе - в правое. Этот процесс повторяется до тех пор, пока не будет достигнуто пустое дерево. В этом месте дерева подключим новый узел и поместим туда число.

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

Рекурсия

Сравнение рекурсии и итерации

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

Рассмотрим вычисление факториала

В Турбо-Паскале разрешена рекурсия, которая заключается в том, что процедура или функция могут вызывать сами себя. Пример вычисляет факториал с использованием рекурсивной функции Factor.

Пример

Исходные данные:

N - целое неотрицательное число.

Результат:

факториал числа N

program FactorRec; {вычисление факториала с использованием рекурсии} var

N: integer; function Factor(N: integer): integer; begin

if N = 0 then Factor := 1 else Factor := N * Factor(N-1);

end;

begin {начало программы}

writeln('введите целое число'); read(N); writeln('Факториал ', N:4, '=', Factor(N));

end.

С помощью выражения Factor(N-1) эта функция будет вызывать сама себя до тех пор, пока значение параметра не станет равным 0. При каждом повторном вызове функции создается новый экземпляр памяти для всех локальных переменных и для самой функции, который запоминается в стеке. Пусть N = 4, тогда в результате выполнения функции Factor будет создан стек, представленный на Рис.9. Этот процесс называется процессом развертывания рекурсии.

Рис. 9. Процесс развертывания рекурсии

Как только N становится равным 0, вычисляется первое значение факториала Factor = 1, которое затем подставляется в соответствующий экземпляр памяти. Теперь на каждом очередном шаге значения всех членов выражения N * Faсtor(N - 1) известны и алгоритм подставляет в это выражение значение, полученное на предыдущем шаге. Начинается процесс свертывания рекурсии, представленный на Рис.10, и вычисляется значение Factor = 24.

Рис. 10. Процесс свертывания рекурсии

Отметим, что вычисление выражения в процессе свертывания рекурсии осуществляется с запомненным значением N, поскольку N передается в функцию по значению (без параметра Var). Так, на 4-м шаге в выражение подставляется значение Factor(0)=1 и N = 1, на 3-м шаге - Factor(1) = 1 и N = 2 и т.д. Для сравнения приведем программу в примере 51, где рекурсия заменяется обычной итерацией.