Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

pascal_lections

.pdf
Скачиваний:
14
Добавлен:
02.04.2015
Размер:
1.43 Mб
Скачать

Procedure MasOutput(m,n:Tind; A:TMas); Var i,j:Tind;

Begin Writeln;

writeln('итоговый массив :'); for I:=1 to m do

begin

for j:=1 to n do Write(A[i,j]:3); WriteLn;

End;{for i} End;{procedure}

{переменные программы}

VAR

m,n,Imin :TInd; B :Tmas;

{программа}

BEGIN MasInput(m,n,B);

PoiskMin(m,n,B,Imin);

Smena(m,n,B,Imin);

MasOutput(m,n,B);

readln;

END.

Подпрограммы. Функции

Функция – подпрограмма, у которой произвольное количество входов и ровно один выход, причем в отличие от процедуры имя функции выполняет дополнительную нагрузку – оно совпадает с именем выходного параметра.

Поэтому тело функции должно содержать хотя бы один оператор присваивания имени функции какого-либо значения или выражения.

Структура функции имеет вид:

function Имя(список_формальных_параметров) :тип_результата;

label

описание локальных меток,

const

констант, типов и переменных

type

 

var

 

procedure

описание внутренних

function

процедур и функций

begin

 

...

 

end;

 

У функции помимо основного выходного параметра, по имени совпадающего с именем функции, могут быть и дополнительные выходные параметры, в качестве которых выступают параметрыпеременные. Их применение и описание аналогично описанию параметров-переменных для процедур.

Пример. Поиск максимального элемента одномерного массива.

21

PROGRAM MaxElem;

Uses crt;

Const RAZ=10;

Type

TInd=1..RAZ;

TMas=array [TInd] of integer;

Procedure MasOutput(m:integer); begin

writeln(‘максимальный элемент равен ’, m); end;

Function MasInput(var A:TMas) :TInd; Var I,N:TInd;

begin

write(‘введите размер массива : ’); readln(N);

writeln;

randomize;

for I:=1 to N do begin

A[I]:=random(100);

Write(A[I]:4);

end;

writeln;

MasInput:=N; {размерность массива} end;

Function PoiskMaxElem(A:TMas; N:TInd) :integer;

Var I:TInd; MaxEl:integer;

Begin

MaxEl:=A[1];

For I:=2 to N do

If A[I]>MaxEl then MaxEl:=A[I];

PoiskMaxElem:=MaxEl;

End;

VAR

N:TInd; A:TMas; Z:integer;

BEGIN

N:=MasInput(A); {размерность массива N, и сам массив А}

Z:=PoiskMaxElem(A,N);

MasOutput(Z);

END.

Параметры процедур и функций.

Открытые параметры-массивы

В заголовках процедур открытые параметры-массивы описываются следующим образом:

Procedure ProcName (Mas :array of MasType);

Передаваемые фактические параметры должны по типу совпадать с описанным типом MasType, но по размерности они могут быть различными: как простой переменной типа MasType, так и массивом любой длины.

22

При этом все открытые параметры-массивы имеют нулевую базу, то есть диапазон изменения индекса фактического массива будет лежать в пределах от 0 до N-1, где N – общее число элементов массива.

Для определения характеристик переданного фактического массива в теле процедуры используются функции:

Low – возвращает индекс первого элемента массива (0), High – возвращает индекс последнего эле-та массива (N-1), SizeOf – возвращает фактический размер массива (N).

Пример.

Сортировка вектор-массивов различной длины.

Program Sort;

Uses crt;

Const

M = 10;

N = 15;

Type

Tvector1 = array [1..M] of integer;

Tvector2 = array [1..N] of integer;

Var

Vector1 :Tvector1;

Vector2 :Tvector2;

Procedure VectorSort( var vector :array of integer );

Var

S, I, J :integer;

Begin

For I:=0 to High(vector)-2 do

For J:=0 to High(Vector)-I-1 do

If Vector[J]<Vector[J+1] then

Begin

S:=Vector[J];

Vector[J]:=Vector[J+1];

Vector[J+1]:=S;

End;

End;

Procedure VectorInput(var Vector :array of integer); Var I:integer;

Begin ClrScr;

Writeln(‘введите ’, High(vector)+1,

‘ элементов типа integer :’); for I:=0 to High(vector) do

begin

write(‘элемент ’,(I+1):3,’ : ’); readln(vector[I]);

end;

writeln;

end;

Procedure VectorOutput(var vector :array of integer);

Var I:integer;

Begin

Writeln(‘результат :’);

For I:=0 to High(vector) do write(Vector[I]:4);

Writeln;

Readln;

End;

BEGIN

VectorInput(vector1);

VectorSort(vector1);

23

VectorOutput(vector1);

{==}

VectorInput(vector2);

VectorSort(vector2);

VectorOutput(vector2);

END.

Рекурсия и опережающее описание.

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

Получается, так называемая, рекурсия – вызов подпрограммой самой себя.

Рекурсия бывает прямой и косвенной.

Прямая рекурсия – подпрограмма вызывает саму себя из собственного набора операторов. Косвенная рекурсия – подпрограмма содержит вызов другой подпрограммы, которая в

свою очередь содержит вызов данной подпрограммы.

Для того чтобы использовать косвенную рекурсию необходимо использовать опережающее описание.

Опережающее описание представляет собой заголовок процедуры, список параметров, (тип возвращаемого значения – для функции) и ключевое слово FORWARD.

Описание самой процедуры (ее тело) представляет собой только заголовок, без списка параметров.

Пример опережающего описания

Program recurs;

Uses crt;

{опережающее описание}

Procedure Rec1(i: integer); forward;

Procedure Rec2(i: integer);

Begin

Writeln(‘рекурсия’);

Rec1(i);

End;

Procedure Rec1;

Begin

If i>0 then

Begin

Writeln(‘взаимная ’);

Rec2(i-1);

End;

End;

BEGIN

Clrscr;

Rec1(3);

END.

Результат работы программы: Взаимная рекурсия Взаимная рекурсия Взаимная рекурсия

24

Рекурсия

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

Глубина рекурсии – максимальное число рекурсивных вызовов процедуры.

Текущий уровень рекурсии – это число рекурсивных вызовов в текущий момент времени.

В общем случае любая рекурсивная процедура Rec включает в себя некоторое множество операторов S и один или несколько операторов рекурсивного вызова P.

Формы рекурсивных процедур.

1. форма с выполнением действий до рекурсивного вызова (рекурсивный спуск)

procedure Rec; begin

S;

if условие then Rec; end;

2. форма с выполнением действий после рекурсивного вызова (рекурсивный возврат)

procedure Rec; begin

if условие then Rec; S;

end;

3. форма с выполнением действий до и после рекурсивного вызова (рекурсивный спуск и возврат)

procedure Rec; begin

S1;

if условие then Rec; S2;

end;

или

procedure Rec; begin

if условие then begin

S1;

Rec;

S2;

end;

end;

При любых формах рекурсии необходимо использовать некоторое условие, которое прекратит цикл рекурсивных вызовов.

25

Выполнение действий на рекурсивном спуске

Вычисление факториала числа N

Program factorial_down;

Var N :integer;

Function fact_down(fact:longint; I,M:integer) :longint; Begin

{накопление факториала} fact:=fact*I;

{рекурсивный вызов}

if I=M then fact_down:=fact

else fact_down:=fact_down(fact,I+1,M); End;

BEGIN

Write(‘Input N: ‘);

Readln(N);

Writeln(‘Factorial N! = ‘, fact_down(1,1,N));

END.

N=5. N!=5!=120

Текущий

Рекурсивный спуск

 

 

Рекурсивный возврат

уровень

 

 

 

 

 

рекурсии

 

 

 

 

 

0

Ввод (N=5)

 

Fact_down(1,1,5);

Вывод: N!=120

1

Fact:=1*1 (1)

 

I=1

Fact_down(1,2,5);

Fact_down:=120;

2

Fact:=1*2 (2)

 

I=2

Fact_down(2,3,5);

Fact_down:=120;

3

Fact:=2*3 (6)

 

I=3

Fact_down(6,4,5);

Fact_down:=120;

4

Fact:=6*4 (24)

 

I=4

Fact_down(24,5,5);

Fact_down:=120;

5

Fact:=24*5 (120)

 

I=5

Fact_down:=120;

Fact_down:=120;

Выполнение действий на рекурсивном возврате

Вычисление факториала числа N

Program factorial_up;

Var N :integer;

Function fact_up(I:integer) :longint; Var fact:longint;

Begin

{рекурсивный вызов} if I=1 then fact:=1

else fact:=fact_up(I-1);

{накопление факториала} fact_up:=fact*I;

end;

BEGIN

Write(‘Input N: ’);

Readln(N);

Writeln(‘Factorial N! = ‘, fact_up(N));

END.

26

N=5. N!=5!=120

Текущий

Рекурсивный спуск

Рекурсивный возврат

уровень

 

 

 

 

рекурсии

 

 

 

 

0

Ввод (N=5);

Fact_up(5)

Вывод: N!=120

1

I=5

Fact:=fact_up(4);

Fact_up:= 24*5 (120)

2

I=4

Fact:=fact_up(3);

Fact_up:= 6*4

(24)

3

I=3

Fact:=fact_up(2);

Fact_up:= 2*3

(6)

4

I=2

Fact:=fact_up(1);

Fact_up:= 1*2

(2)

5

I=1

Fact:=1

Fact_up:= 1*1

(1)

Выполнение действий на рекурсивном спуске и возврате

Вывести на печать символы введенной строки в обратном порядке

EOLN – функция, возвращает TRUE если строка закончилась…

program reverse_string;

procedure reverse; var ch :char; begin

if not eoln then begin

read(ch);

reverse;

write(ch);

end;

end;

BEGIN

writeln('type any string :'); reverse;

END.

Входная строка ‘HELLO’:

Текущий

Рекурсивный спуск

 

Рекурсивный

уровень

 

 

 

возврат

рекурсии

 

 

 

 

0

Reverse;

 

 

 

1

EOLN=False;

input: H;

Reverse;

Output: H;

2

EOLN=False;

input: E;

Reverse;

Output: E;

3

EOLN=False;

input: L;

Reverse;

Output: L;

4

EOLN=False;

input: L;

Reverse;

Output: L;

5

EOLN=False;

input: O;

Reverse;

Output: O;

6

EOLN=True;

 

 

 

27

Пример 1. Вычислить значение целой степени N числа X. 1. без использования рекурсии

A X N X X X X ...X

N раз

function power(X:real; N:integer) :real; var I:integer; A:real;

begin A:=1;

For I:=1 to N do A:=A*X; Power:=A;

end;

2. с использованием рекурсии (рекурсивный возврат)

A X N X X N 1 X X X N 2 ... X X X X ...X 1

function power(X:real; N:integer) :real; begin

if N=0 then power:=1

else power:=X*power(X,N-1); end;

Пример 2. Вычисление факториала

1. без использования рекурсии

B N!1 2 3 4 ...N

function fact(N:integer) :integer; var I,B :integer;

begin B:=1;

For I:=2 to N do B:=B*I; Fact:=B;

end;

2. с использованием рекурсии (рекурсивный возврат)

B N! N (N 1)! N (N 1) (N 2)! ...

N(N 1)(N 2)...1function fact(N:integer)

:integer;

 

begin

 

if N=0 then fact:=1

 

else fact:=N*fact(N-1);

 

end;

 

Пример 3. Вычисление значения биномиального коэффициента

C m

n!

fact(n) div fact(m) div fact(n-m)

 

 

 

 

n

m! (n m)!

 

 

 

28

Рекурсия и опережающее описание.

Пример «Ханойские Башни»

(Ханой – древняя столица Вьетнама)

Для игры используется платформа, на которой укреплены три стержня. На стержни насаживаются диски различного диаметра. Изначально все диски установлены на левом стержне по возрастанию диаметра снизу-вверх, то есть внизу самый большой диск, сверху – самый маленький. Цель игры – перенести башню из дисков с левого стержня на правый. За один раз можно переносить только один диск. И при этом можно насаживать только диск с мЕньшим диаметром на диск с бОльшим диаметром.

program hanoy_tower_2; uses tpcrt;

var K: integer;

{ n - число дисков

на

стержне

Source

}

{ Source

- исходный стержень

 

}

{

Dest

-

стержень,

на

который

нужно переставить диски }

{

Temp

-

вспомогательный стержень (рабочий)

}

procedure MoveDisk(n:integer;

Source, Dest, Temp :char);

begin

if n=1 then

WriteLn('переставить диск 1 со стержня ', Source, ' на стержень ',Dest)

else begin

{переставляем n-1 верхних дисков с исходного стержня на вспомогательный, используя целевой стержень в качестве промежуточного}

MoveDisk(n-1,Source,Temp,Dest);

WriteLn('переставить диск ',n:2,' со стержня ', Source, ' на стержень ',Dest);

{переставляем все n-1 дисков со вспомогательного стержня на целевой стержень, используя исходный стержень в качестве промежуточного}

MoveDisk(n-1,Temp,Dest,Source); end;

end;

BEGIN clrscr;

writeln('Ханойские Башни'); write('введите число дисков : '); readln(K);

writeln('решение :'); MoveDisk(K,'A','C','B'); readln;

END.

29

D 1

D 2

D 3

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

D

2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

D

3

 

 

 

 

 

 

 

 

D

1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

D

3

 

 

D

2

 

 

 

D

1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

D

1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

D

3

 

 

D

2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

D

1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

D

2

 

 

 

D

3

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

D

1

 

 

 

D

2

 

 

 

D

3

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

D

2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

D

1

 

 

 

 

 

 

 

 

 

D

3

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

D

1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

D

2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

D

3

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

A

 

 

B

C

30

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]