Рекурсивные подпрограммы основаны на их обращении к самим себе [6]. Описание действий в таких подпрограммах обязательно содержит терминальную ситуацию, в которой результат получается непосредственно без рекурсивного вызова. Покажем пример реализации действий для следующей задачи: методом слияния объединить два вектора из целых чисел, отсортированных по нарастанию значений их элементов.
Метод слияния двух отсортированных массивов A и B из n и m элементов соответственно, что называется, интуитивно понятен. В последнюю позицию результирующего вектора C сначала помещают наибольший из элементов векторов A и B. Номер следующего элемента (n или m) в том векторе, из которого его взяли, уменьшается на 1. Этот элементарный шаг можно повторять рекурсивно. Если один из векторов уже переписан в вектор C, то в C помещают остатки другого. Терминальная ситуация наступает, когда все элементы векторов A и B будут переписаны в C, чему соответствует условие n + m = 0.
Сначала сконструируем основную форму, представленную на рисунке. Затем создадим модуль с рекурсивной процедурой слияния и вспомогательной процедурой перевода строки в вектор. Для этого выполним команду File/New/Unit – Delphi for Win32. В результате появится заготовка модуля с заголовками интер-фейсной секции и секции реализации. Заносим в них код, представленный ниже.
unit Unit2;
interface
const
k = 100;
type
vector = array[1..k] of integer;
procedure Sliyanie (n, m : byte; a, b : vector; var c : vector);
procedure StrToVector(s : string; var n : integer; var v : vector);
implementation
uses SysUtils;
procedure Sliyanie (n, m : byte; a, b : vector; var c : vector);
{a и b - исходные векторы, c - результат их слияния}
{сначала n - размер вектора a, m - размер вектора b}
begin
if m + n = 0 then exit {Терминальная ситуация - когда все элементы}
else begin {из вектора a и вектора b помещены в вектор c}
if n = 0 then begin {Если из вектора a все элементы взяты в вектор c,}
c[n + m] := b[m]; {то помещаем в него элемент вектора b}
m := m-1
end
else if m = 0 then begin
c[n + m] := a[n]; n := n-1;
end
else if a[n] > b[m] then begin
c[n + m] := a[n]; n := n-1;
end
else begin
c[n + m] := b[m]; m := m-1;
end;
sliyanie(n, m, a, b, c); // Рекурсивный вызов с новыми значениями n и m
end;
end;
procedure StrToVector(s : string; var n : integer; var v : vector);
var // Процедура перевода строки s в вектор v из n элементов
element : string[5]; // Элемент строки
i : integer;
begin
i := 1;
repeat // Цикл обработки чисел в строке
element := copy(s, 1, pos(' ', s)-1); // Элемент строки как число
v[i] := StrToInt(element);
delete(s, 1, pos(' ', s));
inc(i);
until pos(' ', s) = 0;
v[i] := StrToInt(s);
n := i;
end;
end.
Сообщение об ошибке Undeclared identifier: ' StrToInt ' при компиля-ции потребует добавления строки uses SysUtils; после слова implementation. Созданный модуль необходимо подключить к проекту, для чего выполняют одну из команд: File/Use Unit… или Project/Add to Project…. И наконец, сам обработчик щелчка по кнопке “Объединить” имеет вид:
procedure TForm1.Button1Click(Sender: TObject);
var
v1, v2, v3 : vector; i, n, m : integer;
begin
StrToVector(Edit1.Text, n, v1);
StrToVector(Edit2.Text, m, v2);
Sliyanie(n, m, v1, v2, v3);
for i := 1 to n + m do
Edit3.Text := Edit3.Text + ' ' + IntToStr(v3[i]);
end;
Варианты задания
Создать проект из двух модулей: первый модуль отвечает за интерфейс приложения, а второй содержит рекурсивную подпрограмму в соответствии с вариантом задания.
1. Вычислить и показать первые 10 чисел Фибоначчи: F(1) = 1, F(2) = 1, F(n) = F(n-1) + F(n-2).
2. Вычислить значения первых 5 полиномов Лежандра для x = 1 и x = 0.6 : , , .
3. С погрешностью 0.001 уточнить методом дихотомии корень уравнения = 0 на отрезке [0; 4].
4. С погрешностью 0.001 уточнить по методу Ньютона корень уравнения ln(x) – x + 1.8 = 0 на отрезке [2; 3].
5. Уточнить корень уравнения ln(x) – x + 1.8 = 0 на отрезке [2; 3] методом простой итерации с погрешностью 0.001.
6. Используя итерационную формулу , вычислить с погрешностью 0.001 и .
7. Найти с погрешностью 0.001 и , по формуле q := (q + n/q)/2, в которой n – исходное число, а q – приближение к результату.
8. Определить наибольший элемент в векторе из n чисел.
9. Методом прямоугольников вычислить с погрешностью 0.001 .
10. С погрешностью 0.001 вычислить .
11. С погрешностью 0.001 вычислить .
12. Для x = 0.8 вычислить значения первых 6 полиномов Эрмита: , , .
13. Вычислить и , использовав следующее представление квадратов чисел: , , , …
14. Вычислить сумму элементов вектора из n чисел.
15. Для x = 0.5 вычислить значения первых пяти полиномов Лагерра: , , .
16. Вычислить значения первых пяти многочленов Чебышева: , , для x = 0.5.
17. Подсчитать количество переносов колец ханойской башни с одного столба на другой. Можно переносить только по одному кольцу, класть меньшее на большее, используя третий столб. Исходная и результирующая башни имеют на вершинах самое маленькое кольцо.
18. Вычислить p + (p + 1) + (p + 2) + … + (p + n) для p = 0.7 и n = 10, а также для p = 0.5 и n = 15.
19. С погрешностью 0.0001 вычислить e = 1 + 1/1! + 1/2! + 1/3! + …
20. Вычислить для n = 7 и n = 10 выражение .