Работа с двухмерными массивами (матрицами)

Двумерные массивы называют матрицами. У них первый индекс означает номер строки, второй – номер столбца.

Пример 1. Описания типов двумерных массивов:

type quad_matr = array[1..n,1..n] of real;

mas_2d = array[1..n+m,1..10] of integer;

Пример 2. Непосредственные описания переменных как двумерных массивов:

var A,B,C:array[1..5,1..10] of integer;

matr:array[1..m,1..m] of longint;

Графически матрицы изображают в виде таблиц. Например, на рис.8.1 дана матрица с 4 строками и 4 столбцамикоторую обозначимА. При размещении в памяти и обработке многомерных массивов действует следующее правило адресации элементов в массиве: первым возрастает самый правый индекс, затем второй справа и т.д. Для матриц это означает, что их элементы располагаются по строкам. В математике матрицу А, имеющую n строк и m столбцов обозначают как А(n´m).

-11 -23   -11 -23   -11 -23
-4 -10 -68 -27 -4 -10
-14 -84 -14 -84 -14 -84
-68 -27 -4 -10 -68 -27

Рис.8.1 Рис. 8.2 Рис. 8.3

Пример 3. Элементы матрицы А[1..4,1..4](рис.8.1) располагаются в памяти в следующем порядке: А[1,1]; А[1,2]; А[1,3]; А[1,4]; А[2,1]; А[2,2]; А[2,3]; А[2,4]; А[3,1]; А[3,2]; А[3,3]; А[3,4]; А[4,1]; А[4,2]; А[4,3]; А[4,4].

Если рассматривать матрицу А(n´m) в виде линейного массива L длины n × m, то каждой паре индексов [i,j] в матрице А взаимно однозначно соответствует индекс, равный ((i-1)× m + j) в линейном массивеL.

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

Пример 4.Инициализация матрицы M[1..2,1..3] с использованием типизированной константы:

type Matr= Array[1..3,1..2] of Integer;
const M: Matr= ( (2, -8)
(-5, 41)
(53, -26));

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

Пример 5.Ввод в матрицу a размерами 5´4 случайных чисел, лежащих на отрезке [0;1]:

var a:array[1..5,1..4] of real;

i,j:integer;

Begin

for i:=1 to 5 do

for j:=1 to 4 do a[i,j]:=random;

End.

Пример 6.Построчный вывод элементов матрицы a из примера 5 размерами 5´4: случайных чисел, лежащих на отрезке [0;1]

for i:=1 to 5 do begin

for j:=1 to 4 do write(' a[',i,',',j,']=',a[i,j]:8:6);{вывод строки элементов}

writeln;{переход на очередную строку}

End;

Простейшим видом задач является поиск положения и значения элемента матрицы, обладающего каким-либо свойством.

Пример 7. Ввести с клавиатуры элементы матрицы M[1..2,1..3]с элементами типа integer и вывести матрицу на экран. Определить в ней максимальный отрицательный элемент. Найденный элемент и его номер выдать на экран. Если в матрице нет отрицательных элементов, вывести сообщение “No”.

Решение. Обозначим искомый номер строки элемента через M_str, столбца - через M_stl его значение – черезMax. Начальное значение Maxпримем равным (-32768) – минимально возможному значению типа integer. В качестве начального значения номера M_str примем 0 - номер не существующей строки: M_str=0. Если значение M_str=0не изменилось до конца расчета, то это означает, что ни одного отрицательного элемента в матрице нет.

var a:array[1..2,1..3] of integer;

i,j,M_str,M_stl,Max:integer;

Begin

for i:=1 to 2 do{ввод элементов матрицы с клавиатуры}

for j:=1 to 3 do begin

writeln('vvedite element a[',i,',',j,']=');{запрос на ввод элемента a[i,j]}

read(a[i,j]);{ввод элемента a[i,j]}

End;

for i:=1 to 2 do begin{вывод матрицы на экран}

for j:=1 to 3 do write(' a[',i,',',j,']=',a[i,j]:6);{вывод строки элементов}

writeln;{переход на очередную строку}

End;

Max:=-32768; M_str:=0; {начальные присвоение значения Maxи M_str}

for i:=1 to 2 do

for j:=1 to 3 do

if(a[i,j]<0)and(a[i,j]> Max)then{сравнение отрицательных элементов матрицы с Max }

begin Max:=a[i,j]; M_str:=i; M_stl:=j end; {коррекция Max, M_strи M_stl}

if M_str=0 then writeln(' NO!') else{проверка, была ли хоть одна коррекция Max}

writeln(' Max:=',Max,' M_str=',M_str,' M_stl=', M_stl);{вывод результатов}

End.

Для определенности будем рассматривать целочисленную матрицу с названием a, число строк которой обозначено как n, число столбцов – как m. Целочисленные индексы, пробегающие по строкам и столбцам, обозначимi и j. Матрицы, у которых числа строк и столбцов равны (n=m), называют квадратными. Пример квадратной матрицы а(4´4)дан на рис.8.1. Для квадратных матриц вводят понятия главной диагонали – упорядоченный набор элементов вида{m[1,1], m[2,2], ..., m[n,n]}, у которых совпадают номера строки и столбца. У матрицы на рис.8.1. на главной диагонали стоят элементы: а[1,1]=5, а[2,2]=6, а[3,3]=72, а[4,4]=-27.

Рассмотрим типовые операции, предусматривающие изменение значений элементов матрицы. Для круговой пересылки целых величин используем вспомогательную целую величину t. Фрагменты кода, выполняющие операции, даны для матрицы а(n´m) (a[1..n,1..m]).

1. Перестановка строк и столбцов:

а) перестановку строк с номерами r и s:

for j:=1 to m do{перебор всех столбцов матрицы от 1 до m }

begin t:=a[r,j];a[r,j]:=a[s,j];a[s,j]:=t end;{круговая пересылка элементов строк r,s}

б) перестановку столбцов с номерами p и q:

for i:=1 to n do{перебор всех строк матрицы от 1 до n }

begin t:=a[i,p];a[i,p]:=a[i,q];a[i,q]:=t end;{круг. пересылка элементов столбцов p,q}

Для матрицы с рис.8.1 результаты перестановки строк 2 и 4 даны на рис. 8.2, перестановка столбцов 1 и 2 - на рис. 8.3.

2. Умножение строк и столбцов на постоянные множители:

а) умножение строки с номерам rна постоянный множитель c:

for j:=1 to m do a[r,j]:=a[r,j]*c; {проход по всем столбцам от 1-m,умножение элементов }

б) умножение столбца с номером p на постоянный множитель c:

for i:=1 to n do a[i,p]:=a[i,p]*c:={проход по всем строкам от 1-n,умножение элементов }

Для матрицы с рис.8.1 результат умножения ее строки 2 на множитель 1,5 дан на рис. 8.4.

3. Прибавление (вычитание) из одной строки другой, умноженной на постоянный множитель:

а) прибавление к строке с номерам rстроки с номеромs,умноженной на постоянный множитель c:

for j:=1 to m do a[r,j]:=a[r,j]-a[s,j]*c; {проход по всем столбцам от 1-m,сложение}

б) вычитание выполняется аналогично с заменой “+” на “-”.

Для матрицы на рис.8.1 результат вычитания из строки 1 строки 2, умноженной на 3, дан на рис. 8.5.

4. Транспонирование матриц – операция, при которой ее строки и столбцы меняются местами:

транспонирование матрицы a[1..n,1..m], результат - в матрице b[1.. m,1..n]:

for i:=1 to n do

for j:=1 to m do b[i,j]:= a[j,i];

Для матрицы с рис.8.1 транспонированная матрица дана на рис. 8.6.

5. Сложение (вычитание) матриц – операция, при которой элементы новой матрицы являются суммой (разностью) соответствующих элементов исходных матриц:

определение матрицы с[1.. m,1..n] – суммы матриц a[1..n,1..m] и b[1..m,1..n]:

for i:=1 to n do

for j:=1 to m do с[i,j]:= b[i,j]+a[j,i];

-11 -23   -29 -59   -4
-6 -15 -68 -27 -11 -14
-14 -84 -14 -84 -23 -68
-68 -27 -4 -10 -10 -84 -27

Рис.8.4 Рис. 8.5 Рис. 8.6

Пример 8. Ввести с клавиатуры элементы квадратной матрицы A[1..3,1..3]с элементами типа integer. Из A получить матрицу В, в которой вместо столбца, содержащего минимальный элемент матрицы A, вставлена строка, содержащая максимальный элемент A. Номера строки с максимальным элементом, столбца с минимальным элементом и матрицу В выдать на экран.

Решение. Обозначим номер строки с максимальным элементом A через Str_max, номер столбца с минимальным элемента - черезStl_min, текущие значения максимума и минимума – через max,min. Коды операторов для ввода элементов матрицы с клавиатуры и вывода ее на экран совпадают с примером 7 с учетом изменения числа строк, поэтому в решении они не приводятся. После ввода матрицы A и ее исходного вывода на экран вначале определяются номера Str_max и Stl_min. Затем производится пересылка A в В и требуемая коррекция матрицыВ.

var a,b:array[1..3,1..3] of integer;

i,j,max,min,Stl_min,Str_max,c:integer;

Begin

…///ввод элементов матрицы с клавиатуры и вывода ее на экран - по примеру 7

Str_max:=1; Stl_min:=1; max:=a[1,1]; min:=a[1,1];{начальные присвоения значений}

for i:=1 to 3 do{поиск номеров: Str_max-строки с макс.эл. и Stl_min столбца с мин. эл.}

for j:=1 to 3 do begin

if a[i,j]<min then

begin min:=a[i,j];Stl_min:=j end;{поиск столбца с минимальным элементом}

if a[i,j]>max then

begin max:=a[i,j];Str_max:=i end{поиск строки с максимальным элементом}

End;

writeln(' Stl_min=',Stl_min,' Str_max=',Str_max);{вывод номеров столбца и строки}

В:=A;{начальное формирование матрицы В}

for i:=1 to 3 do

b[i,Stl_min]:=a[Str_max,i];{коррекция матрицы В }

for i:=1 to 3 do begin{вывод результирующей матрицыВ }

for j:=1 to 3 do write(' b[',i,',',j,']=',b[i,j]:8);{вывод строки элементов}

writeln;{переход на очередную строку}

End;

End.

Наряду с рассмотренными выше в линейной алгебре рассматривается еще целый ряд других операция с матрицами - умножение их на вектор, на матрицу, расчет определителя, определение обратной матрицы и т.д.

Вопросы для проверки знаний.

1. Как располагаются элементы двумерного массива в памяти ?

2. На какое место в памяти, начиная с начала записи массива а(10´10), попадет его элемент a[8,5]?

3. Какие матрицы называют квадратными ?

4. Что называют главной диагональю квадратной матрицы ?

5. Как можно перечислить все элементы главной диагонали при помощи одного цикла ?

6. Какое преобразование матрицы называют транспонированием ?

Практические задания.

1. Разработать и отладить код программы, в которой:

а) вводятся с клавиатуры значения элементов целочисленной матрицы A[1..3,1..3],

б) матрица выводится на экран,

в) определяется максимальный элемент матрицы, который затем прибавляется ко всем элементам в нечетных столбцах матрицы,

г) новая матрица выводится на экран.

Динамические массивы

Необходимость работы с большими по числу элементов массивами явилась главной причиной для разработки методов работы с дополнительной динамической памятью. Одним из ее основных результатов явился тип данных "указатель", который в двух словах (по два байта каждое) содержит адрес одиночной величины или массива. Этот тип рассмотрен в Главе 3. Указатель на адрес величины aполучается путем использования префикса ^ перед ней: ^a. Для засылки в указатель адреса уже существующей переменной применяют операцию получения адреса переменной (префикс @ перед ее именем или обращение к функции addr()), для обращения к значению переменной, адрес которой хранится в указателе, к нему примеряется операция разыменования, обозначаемая при помощи суффикса ^.

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

В отличие от статических, динамическими называют массивы, размер которых может изменяться во время исполнения программы. С одной стороны, это дает возможность работать с массивами, не ограничивая заранее их размер предельными объёмами. С другой стороны, более рационально используется память вычислительного устройства за счет выделения массивам реально необходимых ее объёмов. Динамические массивы появились в более поздних версиях Паскаля, с появлением Delphi 4. В отличие от статического случая, переменная динамического массива не содержит все элементы массива, а является указателем на область в памяти, где лежат данные элементы, т.е. на первый элемент массива. Использование динамических массивов освобождает от непосредственного использования указателей в простейших случаях работы с динамической памятью.

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

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

Пример 1. Описания динамических массивов:

type
T1DByteArray : Array of Byte;
{Предварительное описание одномерного динамического массива байтовых величин}T1DIntArray = array of integer;{Предварительное описание одномерного динамического массива целых величин}T2DStringArray : Array of Array of string;{Предварительное вложенное описание двумерного динамического массива строковых величин}var
B: T1DByteArray;
{Присвоение переменной B типа одномерного динамического массива байтовых величин T1DByteArray }StringMas: T2DStringArray;{Присвоение переменной StringMas типа двумерного динамического массива строковых величин T2DStringArray }Ar_Int:array of integer; {Непосредственное описание переменной Ar_Int как одномерного динамического массива целых величин}

При объявлении динамического массива место под него не отводится. Переменная динамического массива представляет собой обычный указатель (4 байта) на начало массива. Если массив еще не объявлен либо количество элементов в нем равно 0 (массив пуст), то переменная равна nil.

Если динамический массив не пуст, то его действительный размер всегда на 8 байт больше того пространства памяти, которое занимают его элементы за счет двух дополнительных 4-байтовых величины. Сразу перед данными (по отрицательному смещению -4) в памяти помещается индикатор количества элементов в массиве. Перед ним (по смещению -8) находится счетчик ссылок на массив. Этот счетчик ссылок позволяет иметь несколько переменных, ссылающихся на одни и те же данные в массиве и не заботиться об управлении памятью. Компилятор самостоятельно следит за доступом к данным и при уменьшении счетчика ссылок до 0 освобождает всю память массива. Нумерация элементов в динамических массивах, в отличие от статических, начинается с 0 (как в языке С).

Присваивание динамических массивов вида Array_A:= Array_Bпо аналогии со статическими возможно, когда:

1) оба массива описаны как динамические и имеют одинаковый тип элементов,

2) размер массива Array_A не превышает (больше либо равен) размеру Array_B, либо Array_A=nil.

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

Удалить динамический массив можно несколькими способами: применением функции Finalize или установкой нулевой длины массива.

Помимо возможности описания массивов без указания их размерности, в Паскале введены следующие основные функции для работы с динамическими массивами:

1) SetLength (mas, number)- устанавливает новый размер массива mas равным number (число элементов);

2) Length (mas)- возвращает количество элементов в массиве mas;

3) Low (mas)_- возвращает индекс первого элемента в массиве mas (всегда 0 для динамических массивов);

4) High (mas)- возвращает индекс последнего элемента в массиве mas;

5) Copy(mas, start_imdex, number) - возвращает подмножество из number элементов массива mas, начиная с номера start_imdex;

6) Slice - используется при передаче динамического массива в процедуры в качестве открытого массива (open arrays).

Сразу после объявления динамический массив пуст. Для работы с ним необходимо задать число элементов в нем с использованием функции SetLength. При повторном применении SetLengthкмассиву его размер изменится. Если новое значение размера больше предыдущего, то а нем сохраняются все прежние значения и в конце добавляются новые нулевые элементы. Если новый размер меньше предыдущего, то массив обрезается до нового размера.

Пример 2. Задание длины массива Ar_Int из примера 1:

SetLength(Ar_Int,10);

В результате в массиве будет задано 10 элементов - от Ar_Int[0] до Ar_Int[9].

Обращение к первому элементу динамического массива Dyn_Ar имеет вид Dyn_Ar[0]или Dyn_Ar[Low (Dyn_Ar)].

Пример 3.Обнуление всех элементов динамического массива Dyn_Arтипаinteger:FillChar(Dyn_Ar [0],Length(Dyn_Ar)*sizeof(integer)); При работе с динамическими, как и статическими массивами необходимо следить, чтобы номера элементов в массивах не выходили за текущие их границы. Иначе компилятор прекращает выполнение программы с выдачей сообщения об ошибке.

Пример 4с использованием динамических массивов А,В и статического С:

var A,B: array of integer;

C: array[0..10] of integer;

Len, i: Integer;

Begin

Len:=4; SetLength (A,Len);//Создание дин. массива А(0,0,0,0)

for i:=0 to Len-1 do A[i]:=2*i;// Создание дин. массива А (0,2,4,6)

B:=A;// Копирование дин. массива А (0,2,4,6) в дин массив В

for i:=0 to Len-1 do C[i]:=A[i];// Засылка значений в стат. массив С: C(0,2,4,6)

A[1]:=10;//Изменение значения первого элемента массива А: A[1]:=10

writeln (' Enter values of massiv elements:');

for i:=0 to Len-1 do

writeln (' A[',i,']=',A[i], ' B[',i,']=',B[i], ' C[',i,']=',C[i]);

A:=Copy(A,1,2);//Запись в 2 первых элемента (А[0],A[1]) массива А прежних значений А[1], A[2]

writeln (' Finish values of massiv elements:');

for i:=0 to Len-3 do

writeln (' A[',i,']=',A[i],' B[',i,']=',B[i], ' C[',i,']=',C[i]);

SetLength(A,0); SetLength(B,0); //Удаление динамических массивов А и В

End.

B итоге работы программы на экране пользователя выдается информация:

Первая выдача значений элементов массивов показывает, что присвоение B:=Aв начале задает полную идентичность динамических массивов A иB - изменение A[1]:=10автоматически вызвало такое же изменение в массиве В[1]:=10. Статический массив, в который поэлементно были засланы элементы A, не изменился.

Вторая выдача значений массивов показывает, что применение функции Copy к массиву A вызвало разрыв связи динамических массивов A иB.

8.6.1. Двумерные динамические массивы

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

Рассмотрим матрицу М[1..n,1..m] и соответствующий ей вектор L[0..n×m-1]. Взаимно однозначное отображение множества Мnm пар индексов (i,j) элементов матрицы (у которых 1≤ i ≤ n, 1≤ j ≤ m) на множество Lk значений индекса k элементов L[0≤ k ≤n×m-1], задаваемое функцией

k = k (i, j, m) = (i-1)m +(j-1),

означает, что каждой паре (i,j) из Мnm соответствует единственное значение k. из Lk и наоборот, каждому значению k. из Lk соответствует ровно одна пара (i,j) из Мnm.

Использование функции k = k (i, j, m) позволяет свести работу с динамическими матрицами к работе с обычными одномерными динамическими массивами.

Пример 5.Разработать программу, в которой выполнялись бы следующие действия:

1) ввод с клавиатуры размерности квадратной целочисленной матрицы M[1..n,1..n], затем - коэффициентов матрицы,

2) построчный вывод матрицы M[1..n,1..n] на экран,

3) определение в M[1..n,1..n] суммы всех элементов на главной диагонали,

4) исключение из строк M[1..n,1..n] всех элементы, стоящих на главной диагонали,

5) ) построчный вывод новой матрицы N[1..n,1..(n-1)] на экран,

6) удаление динамических массивов, соответствующих M и N.

Решение. Обозначим номера строк и столбцов матриц через i и j, динамические линейные массивы, соответствующие матрицам, через LM,LN. При удалении диагональных элементов использовано следующее их свойство: в линейном массиве они лежат с промежутками в n элементов. При выборочной записи элементов массива LM в массив LN использованы их текущие номера n_elM и n_elN.

var LM,LN: array of integer;{ Описание дин. массивовLM,LN}

n,i,j,el,S,n_elM,n_elN: integer;

function k(i,j,m:integer):integer; {функция для расчета k = k (i, j, m) = (i-1)m +(j-1) }

begin k:= (i-1)*m + j -1; end;

Begin

writeln (' Vvedite razmernost:');read(n);{запрос на ввод и ввод размерности n }

SetLength (LM,n*n);{Создание дин. массиваLMдля ввода матрицыM[1..n,1..n] }

for i:=1 to n do{ввод элементов матрицы с клавиатуры}

for j:=1 to n do begin

writeln('vvedite element M[',i,',',j,']=');{запрос на ввод элемента M[i,j]}

read(el); LM[k(i,j,n)]:=el;{ввод элемента M[i,j] в линейный массив LM }

End;

for i:=1 to n do begin{вывод матрицы M[1..n,1..n] на экран}

for j:=1 to n do write(' M[',i,',',j,']=',LM[k(i,j,n)]:6);{вывод строки}

writeln;{переход на очередную строку}

End;

S:=0; {расчет суммы S диагон. эл-тов матрицы M[1..n,1..n]}

for i:=1 to n do S:=S+LM[k(i,i,n)];

writeln(' Sum of diagonal ejements=',S);{вывод суммы диагональных элементов M}

SetLength (LN,n*(n-1));{Создание дин. массиваLNдля ввода матрицы N[1..n,1..(n-1)] }

n_elM:=-1;n_elN:=-1;{Задание начальных значений номерам элементов в дин. массивахLM,LN}

for i:=1 to n-1 do begin{Проход по промежуткам между диаг. эл-тами}

n_elM:= n_elM+1; for j:=1 to n do begin n_elM:= n_elM+1; n_elN:=n_elN+1;

LN[n_elN]:=LM[n_elM]{Засылка значений в динамический массив N[1..n,1..(n-1)] }

End end;

for i:=1 to n do begin{Печать динамического массива N[1..n,1..(n-1)] }

for j:=1 to n-1 do write(' N[',i,',',j,']=',LN[k(i,j,n-1)]:6);{вывод строки}

writeln;{переход на очередную строку}

End;

SetLength(LM,0); SetLength(LN,0); //Удаление динамических массивов LM и LN

End.

По аналогии с рассмотренным выше взаимно однозначным отображением k(i, j, m) = (i-1)m +(j-1),множества пар индексов (i,j) элементов двумерного массива (матрицы М[1..n,1..m]) на множество Lk значений индекса k элементов L[0≤k≤n×m-1], можно организовать взаимно однозначные отображения на линейный массив и массивов более высокой размерности. Например, для трехмерного массива М[1..n,1..m,1..p] взаимно однозначное отображение k(i, j, s, m,р) множества троек индексов (i,j,s) на множество Lk значений индекса k элементов L[0≤ k ≤n×m×р-1] имеет вид:

k = k(i, j, s, m,р) = (i-1)×m×р + (j-1) ×р + (s-1).

Вопросы для проверки знаний.

1. Какие массивы называют статическими, а какие - динамическими ?

2. Назовите два вида описания динамических массивов ?

3. Чем принципиально отличается объявление динамического массива от статического с точки зрения появления новых объектов в памяти ?

4. Какое предварительное действие необходимо выполнить после объявления динамического массива для того, чтобы работать с его элементами ?

5. Как переписать динамический массив в статический ?

6. Как удалить динамический массив путем изменения его длины ?

7. Каким образом можно использовать для работы с многомерными массивами аппарат динамических массивов без использования указателей ?

Практические задания.

1.Разработать программу, в которой выполнялись бы следующие действия:

а) ввод с клавиатуры размерности n линейного целочисленного динамического массива L[1..n] и его элементов,

б) расчет суммы элементов массива L[1..n] с выводом ее на экран,

в) удаление динамического массива L[1..n].

2. Разработать программу, в которой выполнялись бы следующие действия:

а) ввод с клавиатуры размерности квадратной целочисленной матрицы M[1..n,1..n], затем - коэффициентов матрицы,

б) построчный вывод матрицы M[1..n,1..n] на экран,

в) смена местами в M[1..n,1..n] первого и последнего столбца,

г) построчный вывод новой матрицы M [1..n,1..(n-1)] на экран,

д) удаление динамического массива, соответствующего M.