Динамические двумерные массивы
Вложенные циклы
Цель работы
Цель работы - приобретение навыков построения вложенных циклических алгоритмов и реализация с их помощью управляющих конструкций повторения.
Заданиe
1. Задайте массив M x N, выполните действия для Вашего варианта. Ввод массива вручную.
1 Найдите наибольший элемент, укажите его положение.
2 Найдите столбец с наибольшей суммой.
3 Найдите столбец с наименьшей суммой.
4 Найдите сумму элементов каждой диагонали.
5 Найдите строку с наибольшей суммой.
6 Найдите строку с наименьшей суммой.
2. Задайте таблицу M x N, выполните действия для Вашего варианта. Ввод данных вручную.
1 Найдите наибольший элемент, укажите его положение.
2 Найдите столбец с наибольшей суммой.
3 Найдите столбец с наименьшей суммой.
4 Найдите сумму элементов каждой диагонали.
5 Найдите строку с наибольшей суммой.
6 Найдите строку с наименьшей суммой.
Теоретические сведения
В качестве оператора в теле цикла можно использовать практически любой оператор, в том числе For, While, Repeat. Такие конструкции называют конструкциями с вложенными циклами. При выборе оператора повторений следует учитывать:
· оператор For применяют только при известном заранее количестве повторений;
· операторы While и Repeat управляют повторениями по логическому условию;
· оператор, находящийся в теле цикла Repeat, всегда будет выполнен минимум один раз;
· в зависимости от условия, оператор, находящийся в теле цикла While, может быть не выполнен ни разу.
Ниже приведены фрагменты алгоритмов с вложенными циклами.
Оператор |
i=0..n |
j=0..k |
Цикл For с вложенным циклом For Forj=0 to k do {Внешний цикл} For i=0 ton do {Вложенный цикл} Оператор; |
i<=n |
Оператор i:=i+1; I:=I+1 |
j<=k |
j:=0; |
i:=0; |
j=j+1 |
Цикл While с вложенным циклом While j:=0; Whilej<=k do {Внешний цикл} begin i:=0: While i<=n do {Вложенный цикл} begin Оператор; i:=i+1: end; {Конец вложенного цикла} j:=j=1; end; |
i>n |
j:=j+1 |
j:=0; |
i:=0; |
Оператор i:+i+1 |
j>k |
Repeat с вложенным циклом Repeat j=0; Repeat i=0; repeat Оператор; i:=i+1; until i>n; j=j+1; Until j>k; |
j:=0 |
i=0..n |
Оператор |
j:=j+1 |
j>k |
Repeat с вложенным циклом For j:=j+1; Repeat for i:=0 to n do Оператор; j:=j+1; Until j>k; |
Пример 1. Ручной ввод массива в поле TEdit
Дано:LabeledEdit1.Text – поле ввода в которое вручную введён массив как строка текста;
введённые значения соответствуют алфавиту вещественных чисел иразделены пробелами;
переменная Mx: T_M - динамический массив (T_M = array of Real); Label1.Caption - метка для вывода номера элемента массива i, и значения элемента массива Mx[i];
Требуется сформировать из данных поля ввода числовые значения массива Mx.
Постановка задачи.
· для выделения одного элемента массива из строки LabeledEdit1.Text, будем в цикле считывать по одному символы и вставлять их во вспомогательную строку S, пока не достигнем пробела, LabeledEdit1.Text[j] <> ' ')
· количество считанных символов фиксирует счётчик элементов текстовой строки j;
· количество сформированных строк фиксирует счётчик числового массива i;
· преобразуем вспомогательную строку S в элемент массива Val(S, Mx[i], Cod);
· эти действия будем повторять, пока количество считанных символов меньше или равно длине строки ввода, j <= Length(LabeledEdit1.Text.
True |
false |
Начало |
Конец |
Повторять: до пробела, i < длины строки |
true |
While |
Until |
Exit |
I=0, j=0 – обнуление счётчиков Очистка метки вывода, Label.Caption |
if |
Недопустимый cимвол |
Схема алгоритма. Ручной ввод массива procedure TForm1.Button1Click(Sender: TObject) |
inc(j); увеличение j S:='' очистка вспомогательной строки |
к S присоединяется очередной символ Inc(j) |
false |
Val(S, Mx[i], Cod) |
Cod <> 0 |
Очистка метки вывода |
Вывод i Mx[i] |
Inc(i) |
Все элементы массива или конец строки |
procedureTForm1.Button1Click(Sender: TObject);
VarCod, i, j : Integer; //Cod – индикатор преобразования Строка-Число;
// i – счётчик числового массива, j – счётчик элементов текстовой строки
S: String; //вспомогательная строка, для формирования очередного элемента
Begin
i:=0; J:=0; //обнуление счётчиков
Label1.Caption:= ''; //очистка метки вывода
Repeat//повторять, пока условие «Until ….» не станет true
inc(j); //увеличивает j на 1, при первом вхождении j=1
S:=''; //очистка вспомогательной строки
{Пока «очередной символ не пробел» и «счётчик j меньше или равен длине строки, повторять}
While(LabeledEdit1.Text[j] <> ' ') and (j <= Length(LabeledEdit1.Text))do
Begin
S:= S + LabeledEdit1.Text[j]; //к S присоединяется очередной символ
Inc(j); //j увеличился на 1, переход на новый виток цикла While
end;//конец While, в S символы одного элемента массива
Val(S, Mx[i], Cod);
//Преобразование символов S в элемент числового массива Mx[i]
ifCod <> 0 //контроль, если Cod =0 – преобразование успешное
then begin//ошибка преобразования
ShowMessage('Недопустимый символ!' );
Label1.Caption:= ''; //очистка метки вывода
exit; //досрочное завершение цикла Repeat
End;
{Преобразование было успешным. Далее вывод счётчика i, табуляция (#9), вывод элемента массива Mx[i], символы конца строки}
Label1.Caption:= Label1.Caption+
IntTostr(i)+#9+ FloatToStr(Mx[i])+#10#13;
inc(i); //увеличивает i на 1
{Если i < старшего индекса массива или j < длины строки цикл Repeat продолжать}
Until(i>High(Mx))or(j> Length(LabeledEdit1.Text)); //конец цикла Repeat
End;
Двумерные массивы
Двумерный массив можно рассматривать как одномерный, у которого каждый элемент сам является массивом, например,
typemat =array [0..5]of array [0..2]ofByte
Такое описание можно заменить более компактным:
typemat = array[0..5, 0..2]of Byte; это двумерный массив, у которого 6 строк [0..5] и 3 столбца [0..2].
Примеры описания двумерных массивов
const N=4; K=3;
type Vector = array [1..N, 1..K ] of Real; //тип массив 4х3}
var M_X : Vector; //переменная массив 4х3}
M_Y : array [1.N, 0..K ] of Byte; //переменная массив 4х4}
M_Z : array [ 1..4, 3..7 ] of Word;
В памяти элементы многомерного массива следуют друг за другом так, что при переходе от младших адресов к старшим наиболее быстро меняется правый индекс массива. Например, для двумерного массива А:array [1..3,1..3]of Byte, последовательность расположения элементов будет следующая:
A[1,1] A[1,2] A[1,3] A[2,1] A[2,2] A[2,3] A[3,1] A[3,2] A[3,3]
Динамические двумерные массивы
При объявлении таких массивов границы индексов не указывают:
var В:array of array of Real; //двумерный массив
Динамические массивы не имеют установленного размера или длины. Глубина вложенности массивов (размерность массива) не ограничена, однако суммарная длина внутреннего представления многомерного массива не может быть больше 2 Гбайт. Распределение памяти и указание границ индексов по каждому измерению динамических массивов осуществляется в ходе выполнения программы путем инициации массива процедурой SetLength.
SetLength(var S; NewLength: Integer) - устанавливает длину переменной динамического массива,
где S - переменная динамического массива;
NewLength - число элементов массива S, нижняя граница индексов
динамического массива всегда 0.
Для освобождения памяти занятой массивом достаточно присвоить идентификатору значение nil или использовать процедуру Finalize.
В многомерных динамических массивах каждый элемент любого из N-1 измерений (N - количество измерений) представляет собой динамический массив и, следовательно, нуждается в инициации.