По первому тесту выполнил дважды задания. Результат получается правильный (проверял калькулятором). Пишет, что "Задание не проверено" и предлагает повторить. |
Использование языка Free Pascal для обработки массивов
5.8 Удаление элемента из массива
Знакомство с алгоритмом удаления элемента из массива начнем со следующей простой задачи. Необходимо удалить третий элемент из массива X, состоящего из 6 элементов. Алгоритм удаления третьего элемента заключается в том, что на место третьего элемента следует записать четвёртый, на место четвёртого — пятый, а на место пятого — шестой.
X[ 3 ] : =X [ 4 ];
X[ 4 ] : =X [ 5 ];
X[ 5 ] : =X [ 6 ];
Таким образом, все элементы с третьего по пятый надо переместить влево на один — на место i-го элемента нужно записать (i+1)-й. Блок-схема алгоритма представлена на рис. 5.25.
Теперь рассмотрим более общую задачу: необходимо удалить m-й элемент из массива X, состоящего из n элементов. Для этого достаточно записать элемент (m+1)-й на место элемента c номером m, (m+2)-й элемент — на место (m+1)-го и т. д., n-й элемент — на место (n–1)-го. Процесс удаления элемента из массива представлен на рис. 5.26.
Алгоритм удаления из массива Х размерностью n элемента с номером m приведён на рис. 5.27.
После удаления элемента4А фактически сдвига части массива на один элемент влево из массива изменится количество элементов в массиве (уменьшится на один), и у части элементов изменится индекс. Если элемент удалён, то на место него приходит следующий, передвигаться к которому (путём увеличения индекса на один) нет необходимости. Следующий элемент сам сдвинулся влево после удаления.
Если обрабатывается массив, в котором часть элементов удаляется, то после удаления элемента не надо переходить к следующему (при этом уменьшается количество элементов). В качестве примера рассмотрим следующую задачу.
Алгоритм решения задачи довольно прост: перебираем все элементы массива, если элемент отрицателен, то удаляем его путём сдвига всех последующих на один влево. Единственное, о чём стоить помнить, — что после удаления элемента не надо переходить к следующему для последующей обработки, он сам сдвигается на место текущего. Блок-схема решения задачи 5.1 представлена на рис. 5.28.
Ниже представлен текст программы с комментариями.
program upor_massiv; var i, n, j : byte; X: array [ 1.. 100 ] of real; begin writeln ( ’введите размер массива ’ ); readln ( n ); {Ввод массива.} for i :=1 to n do begin write ( ’X[ ’, i, ’ ]= ’ ); readln (X[ i ] ); end; writeln ( ’массив X ’ ); for i :=1 to n do write ( x [ i ] : 5 : 2, ’ ’ ); writeln; i : = 1; while ( i<=n ) do {Если очередной элемент массива X[i] отрицателен, то} if x [ i ]<0 then begin {удаляем элемент массива с номером i.} for j := i to n_1 do x [ j ] : = x [ j + 1 ]; {Уменьшаем размер массива.} {Не надо переходить к следующему элементу массива.} n:=n -1; end else {Если элемент не удалялся, то переходим к следующему элементу массива.} i := i +1; writeln ( ’Изменённый массив ’ ); for i :=1 to n do {Вывод преобразованного массива.} write (X[ i ] : 5 : 2, ’ ’ ); writeln; end.
Результаты работы программы представлены на рис. 5.29.
5.9 Вставка элемента в массив
Рассмотрим несложную задачу: вставить число b в массив X(10), между третьим и четвёртым элементами.
Для решения этой задачи необходимо все элементы массива, начиная со четвёртого, сдвинуть вправо на один элемент. Затем в четвёртый элемент массива нужно будет записать b (X[4]:=b;). Но чтобы не потерять соседнее значение, сдвигать на один вправо нужно сначала десятый элемент, затем девятый, восьмой и т. д. до четвёртого. Блок-схема алгоритма вставки приведена на рис. 5.30.
В общем случае блок-схема вставки числа b в массив X(N), между элементами c номерами m и m+1 представлена на рис. 5.31.
Ниже представлен фрагмент программы, реализующий этот алгоритм5При описании массива необходимо предусмотреть достаточный размер для вставки одного элемента..
var i, n,m: byte; X: array [ 1.. 100 ] of real; b : real; begin writeln ( ’N= ’ ); readln ( n ); for i :=1 to n do begin write ( ’X[ ’, i, ’ ]= ’ ); readln (X[ i ] ); end; writeln ( ’Массив X ’ ); for i :=1 to n do write ( x [ i ] : 5 : 2, ’ ’ ); writeln; writeln ( ’m= ’ ); readln (m); writeln ( ’ b= ’ ); readln ( b ); for i :=n downto m+1 do x [ i +1]:=x [ i ]; x [m+1]:=b; n:=n+1; writeln ( ’Изменённый массив ’ ); for i :=1 to n do write (X[ i ] : 5 : 2, ’ ’ ); writeln; end.
5.10 Использование подпрограмм для работы с массивами
Рассмотрим, как можно передавать массивы в подпрограмму. Как известно (см. главу 4), чтобы объявить переменные в списке формальных параметров подпрограммы, необходимо указать их имена и типы. Однако типом любого параметра в списке может быть только стандартный или ранее объявленный тип. Поэтому для того, чтобы передать в подпрограмму массив, необходимо вначале описать его тип6Тип данных массива, объявление массива см. в п. 2.4.9. Подробно работа с массивами описана в данной главе., а затем объявлять процедуру:
type
тип_массива = array [ список_индексов ] of тип;
procedure
имя_процедуры(имя_массива : тип_массива );
...
Например:
type vector=array [ 1.. 10 ] of byte; matrica=array [ 1.. 3, 1.. 3 ] of real; procedure proc (A: matrica; b : vector; var x : vector );
Понятно, что передача в подпрограмму строки вида
имя_переменной : string [ длина_строки ];
которая фактически является массивом7Тип данных "строка", объявление строки см. в п. 2.4.9, должна осуществляться аналогично:
type
тип_строки = string [ длина_строки ];
procedure
имя_процедуры(имя_строки : тип_ строки );
...
Например:
type stroka_5=string [ 5 ]; stroka_10=string [ 1 0 ]; function fun ( S t r : stroka_5 ) : stroka_10;
Массивы в подпрограмму можно передавать, используя понятие открытого массива. Открытый массив — это массив8Тип данных "массив", объявление массива, обращение к массиву см. в п. 2.4.9., при описании которого указывается тип элементов, из которых он состоит, но не определяются границы изменения индексов:
имя_открытого_массива : array of array of... тип;
Например:
var massiv_1 : array of real; massiv_2 : array of array of char; massiv_3 : array of array of array of byte;
Распределение памяти и указание границ индексов по каждому измерению открытых массивов осуществляется в ходе выполнения программы с помощью функции SetLength:
SetLength (имя_открытого_массива, список_границ_индексов );
Для освобождения выделенной памяти нужно выполнить оператор:
имя_открытого_массива:=NIL;
Нижняя граница открытого массива (минимальное значение номера элемента) всегда равна нулю. Верхняя граница (максимальное значение номера элемента) возвращается стандартной функцией:
high (имя_открытого_массива)
Открытые массивы можно использовать при обычной обработке массивов в языке Free Pascal. Рассмотрим использование открытого массива на примере простейшей задачи нахождения суммы элементов массива.
var x : array of real; //Описание открытого массива. s : real; i, n : integer; begin write ( ’ n= ’ ); readln ( n ); //Выделяется память для размещения n вещественных значений: SetLength ( x, n ); for i :=0 to high ( x ) do read ( x [ i ] ); s : = 0; for i :=0 to high ( x ) do s := s+x [ i ]; writeln ( ’сумма= ’, s : 7 : 3 ); x:=NIL; //Освобождение памяти. end.
Открытый массив может быть формальным параметром подпрограммы:
procedure имя_поцедуры(имя_открытого_массива : array of тип; );
Применение открытого массива в подпрограмме позволяет обрабатывать одномерные массивы произвольной длины:
//Процедура предназначена для вывода на экран //сообщений о значениях элементов одномерного массива. //Параметром подпрограммы является открытый массив целых //чисел. procedure outputArray (X: array of integer ); var i : byte; begin //Элементы в открытом массиве пронумерованы от 0 до high(X). for i :=0 to high (X) do //Вывод сообщения: X[номер_элемента]=значение_элемента. writeln ( ’X[ ’, i, ’ ]= ’,X[ i ] ); end; var A: array [ 1.. 10 ] of integer; C: array of integer; i : byte; begin //Формирование одномерного массива А из 10 элементов. for i :=1 to 10 do A[ i ] : = 2*i +1; //Выделяется память для размещения 3 целочисленных значений: SetLengTh (C, 3 ); //Формирование одномерного массива С из 3 элементов. for i :=0 to 2 do C[ i ] : = 1-2*i; //Обращение к подпрограмме. outputArray (A); outputArray (C ); end.
Без использования открытых массивов процедуруoutputArray пришлось бы записать:
//Описание типа: массив целых чисел, //пронумерованных от 0 до 10. type massiv=array [ 0.. 10 ] of integer; //Процедура предназначена для вывода на экран //сообщений о значениях элементов одномерного массива. procedure outputArray (X: massiv; nN, nK : byte ); //Параметры подпрограммы: //1. Массив целых чисел X. //2. Нижняя граница индекса nN. //3. Верхняя граница индекса nK. var i : byte; begin //Элементы массива нумеруются от nN до nK. for i :=nN to nK do writeln ( ’X[ ’, i, ’ ]= ’,X[ i ] ); end;