
- •1 Рекурсия
- •2 Рекурсия и Итерация
- •3 Линейный поиск
- •4 Поиск делением пополам (двоичный поиск)
- •5 Сортировка
- •6 Сортировка простыми включениями.
- •7 Сортировка бинарными включениями
- •8 Сортировка простым выбором.
- •9 Сортировка простым обменом (метод пузырька)
- •10 Шейкер сортировка.
- •11 Сортировка включениями с убывающими приращениями (сортировка Шелла).
- •12 Сортировка с разделением (быстрая сортировка).
- •13 Ссылочные типы.
- •14 Динамические структуры данных
- •15 Создание и уничтожение динамических переменных
- •16. Связанные списки
- •17. Связанные списки. Создание очередного элемента. Просмотр списка
- •18. Добавление компонент в середину списка
- •19. Исключение компонент из середины списка
- •20. Рекурсивная обработка списка
- •Вопрос 21
- •22 Деревья.
- •23 Двоичные деревья.
- •24 Двоичное дерево поиска.
- •25 Добавление узла к двоичному дереву.
- •26 Поиск в двоичном дереве.
- •28 Удаление из дерева.
- •29 Деревья общего вида.
- •30 Становление ооп
- •Абстрагирование
- •Иерархия
- •31 Основные концепции
- •2 Наследование
- •3 Индивидуальность объекта.(Про это у меня вообще ничего нет)
- •32 Абстрактные типы данных
- •37 Виртуальные методы.
- •38 Позднее связывание.
- •39 Полиморфизм
- •40 Расширенная совместимость типов.
- •42 Динамические объекты
- •45 Необходимость виртуальных методов.
1 Рекурсия
Объект называется рекурсивным если он содержит сам себя или определен при помощи самого себя. Пример – определение факториала. Мощность рекурсии связана с тем, что она позволяет определить бесконечное множество объектов с помощью конечного высказывания. Точно также бесконечные вычисления можно описать с помощью конечной рекурсивной программы, даже если эта программа не содержит явных циклов. Рекурсивные алгоритмы часто используются в тех случаях когда решаемая задача или вычисляемая функция или обрабатываемая структура данных определены с помощью рекурсии. Необходимое и достаточное средство для рекурсивного представления программ – это описание подпрограмм, т. к. оно позволяет присваивать какому-либо оператору имя с помощь которого можно вызвать этот оператор. Если процедура содержит явное обращение самой к себе, то он называется пряморекурсивной. Если про-ра Р содержит обращение к про-ре А, которая содержит (прямо или косвенно) обращение к про-ре Р, то пр-ра Р называется косвенно рекурсивной. Следо-но использование рекурсии не всегда видно из текста программы. ри выполнении правильно организованной рекурсивной подпрограммы осуществляется многократный переход от некоторого текущего уровня организации алгоритма к нижнему уровню последовательно до тех пор, пока, наконец, не будет получено тривиальное решение поставленной задачи. В примере решение при N = 0 тривиально и используется для остановки рекурсии.
Function Fac(n: Integer): Real;
begin
if n < 0 then
WriteLn ('n не может быть <0!!!')
Else
if n = 0 then
Fac := 1
else
Fac := n * Fac(n-l)
end ; {Fac}
Рекурсивный вызов может быть косвенным. В этом случае подпрограмма обращается к себе опосредованно, путем вызова другой подпрограммы, в которой содержится обращение к первой, например:
Procedure A (i : Byte) ;
begin
.......
В (i);
.......
end ;
Procedure В (j : Byte) ;
.......
begin
.......
A(j);
.......
end;
При любом вызове подпрограммы в память компьютера заносится следующая информация:
- текущие значения параметров, передаваемых через значение;
- местонахождение (адреса) параметров переменных;
- адрес возврата, т.е. адрес оператора, который следует за оператором вызова.
Таким образом, при рекурсивном вызове занимаемая область памяти увеличивается очень быстро, что ведет к риску переполнения памяти компьютера. Этого можно избежать путем замены рекурсии на итерацию.
Рекурсию необходимо использовать в случаях, когда написание нерекурсивных алгоритмов является очень сложным: перевод программ на языке ТУРБО ПАСКАЛЬ на язык компьютера, машинная графика, распознавание образов и т.д.
2 Рекурсия и Итерация
Итерация (Пример):
Вычислить факториал: I: =0; F: =1; While I<n do Begin I : =I+1; F : = I+F; End;
Рекурсия и итерация в некотором смысле противоположны. Рекурсия решает задачу от сложного к простому, итерация - от простого к сложному. Текст рекурсивного алгоритма выражает сложный объект через более простой (более простые) такого же типа. Текст итеративного алгоритма описывает процесс строительства, начиная с мелких деталей.
Рекурсивный алгоритм выражает неизвестное через неизвестное, но связь между этими двумя неизвестными довольно проста, математически прозрачна, поэтому доказать правильность алгоритма легко.
Состояния объекта на двух разных шагах итеративного алгоритма - как два состояния недостроенного дома: пока не положен последний кирпич, не очевидно, что получится в конце. Поэтому доказать правильность такого алгоритма обычно довольно сложно.
Ранее нами рассматривались рекурсивные алгоритмы. Но во многих случаях та же задача может быть решена и нерекурсивными методами. Рекурсивный подход к вычислению функций, заданных рекуррентными соотношениями: f(n) = j(f(n-1), n); f(0) = а.
Эту последовательность можно обратить: f(0) = а; f(1) = j(f(0),1); f(2) = j(f(1),2); ... f(1) = j(f(n-1),n),
начав вычисление с отыскания значения функции при минимальном значении аргумента, и используя его для определения следующего и так далее. Такое вычисление, записанное в виде:
y := a;
for i:= 1 to n do
у := j(y, i)
называется итерацией.
Важное различие между рекурсией и итерацией состоит в механизме реализации. Исполнитель рекурсивного алгоритма, как видно ранее, сводит неизвестное к другому неизвестному, накапливая информацию и откладывая реальные вычисления до момента сведения аргумента функции к такому значению, при котором значение функции известно. Исполнитель итеративного алгоритма начинает с известного значения и шаг за шагом преобразует известные уже значения функции в значения для больших аргументов. В этом отношении итерация подобна обратному ходу в реализации рекурсии. Из этих слов (итерационный процесс есть часть рекурсивного) можно сделать вывод о том, что итерация проще (как часть целого) и необходимо решать задачи итерационными методами.
В действительности ситуация сложнее. В нескольких словах ее можно охарактеризовать так: рекурсивное решение задачи состоит из двух частей - прямого хода (сведение задачи к итерационной форме) и обратного (выполнение итераций). Освободив машину от выполнения прямого хода, облегчаем ее работу, но перекладываем эту часть работы на программиста, которому вменяется в обязанность преобразовать программу. Иногда это не составляет труда для программиста, и он сразу может написать итерационный вариант (например, вычисления факториала или чисел Фибоначчи), а иногда проблема будет трудно разрешимой.