Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Практические работы для ИС-271.doc
Скачиваний:
2
Добавлен:
01.05.2025
Размер:
3.07 Mб
Скачать

Лабораторная работа № 17. Разработка программы реализации задачи, содержащей двумерный массив данных.

Цель работы:

  • закрепить теоретические знания о понятии «вложенные циклы»

  • овладение навыками алгоритмизации структур, содержащих двумерные массивы

  • научиться использовать возможности языка программирования для реализации алгоритмов, содержащих двумерные массивы данных

  • закрепить практические навыки по составлению тестов и отладке программы

Оборудование:

  • программная часть – интегрированная среда Turbo Pascal 7.0

  • аппаратная часть - ПЭВМ IBM PC/XT

  • задание на выполнение работы в электронном варианте

Теоретическая часть

Двумерный массив – это одномерный массив, элементами которого являются одномерные массивы. Другими словами, это набор однотипных данных, имеющий общее имя, доступ к элементам которого осуществляется по двум индексам. Наглядно двумерный массив удобно представлять в виде таблицы, в которой n строк и m столбцов, а под ячейкой таблицы, стоящей в i-й строке и j-м столбце понимают некоторый элемент массива a[i][j].

Действительно, если разобраться с тем, что такое a[i] при фиксированном значении i, то увидим, что это одномерный массив, состоящий из m элементов, к которым можно обращаться по индексу: a[i][1], a[i][2], ... , a[i][m]. Схематически это вся i-я строка таблицы. Аналогично, если мы рассмотрим одномерный массив строк, то сможем заметить, что это так же двумерный массив, где каждый отдельный элемент – это символ типа char, а a[i] - это одномерный массив, представляющий отдельную строку исходного одномерного массива строк. Исходя из идеи определения двумерного массива, можно определить рекуррентное понятие многомерного массива:

n-мерный массив – это одномерный массив, элементами которого являются (n-1)-мерные массивы.

Несложно догадаться, что 3-мерный массив визуально можно представить в виде куба с ячейками, где каждый элемент имеет вид a[i][j][k]. А вот с большими размерностями возникают сложности с визуальным представлением, но математическая модель ясна.

По-другому, двумерный массив также называют матрицей, а в том случае, когда n=m (число строк равно числу столбцов) матрицу называют квадратной. В матрицах можно хранить любые табличные данные: содержание игрового поля (шашки, шахматы, Lines и т.д.), лабиринты, таблицу смежности графа, коэффициенты системы линейных уравнений и т.д.

Действия с двумерными массивами

Условимся, что массив а состоит из n строк и m столбцов.

Суммирование элементов каждой строки.

Результатом является массив с именем d, состоящий из n сумм элементов строк:

for i:=l to n do

begin

s:=0;

for j:=l to m do s:=s+a[i,j] ;

d[i]:=s;

end;

Аналогично вычисляется сумма в столбцах, для этого внешний цикл необходимо сделать по переменной j (номер столбца), а внутренний — по i (номер в строке).

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

Переменная min используется для хранения значения минимального элемента, k — номер строки, l — номер столбца, где он находится:

min:=a[1,1]; k:=1; l:=1;

for i:=1 to n do

for j:=1 to m do

if min>a[i,j] then

begin

min:=a[i,j];

k:=i; l:=j;

end;

Умножение матрицы а на вектор x, в результате получается новый вектор у:

for i:=l to n do

begin

s:=0;

for j:=1 to m do

s:=s+a[i,j]*x[j];

y[i]:=s;

end;

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

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

Алгоритм сортировки массива

Рассмотрим задачу сортировки одномерного массива Z длины N. Отсортировать массив – значит расположить его элементы в порядке роста или убывания.

Опишем метод сортировки массива в порядке роста. Сначала выполняется проход по массиву с целью определения в нем наименьшего элемента. Затем производится перестановка этого элемента с первым. Далее совершается второй проход по массиву, начиная со второго элемента. Найденный наименьший элемент переставляется со вторым и т. д. После (N-1)-го прохода с выполнением названных операций массив окажется отсортированным.

Блок-схема этого алгоритма сортировки показана на рис. 9. Она включает 12 блоков. После начала работы в блоке 2 переменная N и массив Z заполняются константами. Затем в блоке 3 проверяется условие о том, нужно ли сортировать массив. Это сводится к установлению факта наличия в массиве нескольких элементов, т. к. массив из одного элемента всегда отсортирован. Если этот факт установлен, то алгоритм приступает к сортировке. Процедура сортировки выполняется в цикле, объединяющем блоки 4-10. В теле этого цикла содержится другой цикл, который образован блоками 6-8. Его назначение станет ясно из дальнейшего разбора алгоритма. После входа в наружный цикл его счетчик i примет значение 1, что в рамках нашего метода подразумевает первый проход по массиву.

Далее будут выполнены блоки 5-10, составляющие тело наружного цикла. В блоке 5 размещены две вспомогательные переменные V и L. Первая из них предназначена для фиксирования наименьшего элемента, а вторая – для запоминания его индекса. Так как i = 1, то при первом проходе в блоке 5 V примет значение первого элемента, а L значение 1. Затем во внутреннем цикле, образованном блоками 6-8, где его счетчик j будет изменяться от 2 до N, последовательно проводится сравнение соответствующих элементов массива Z со значением переменной V. При этом всякий раз, как будет найден меньший чем v элемент, значение V будет заменено на значение этого элемента, а в переменной L будет зафиксирован его индекс. Понятно, что после выполнения внутреннего цикла в переменной V будет содержаться значение, равное наименьшему элементу, а в L – индекс этого элемента. В блоке 9 далее проверяется, не является ли наименьший элемент первым элементом массива. Если это не так, то в блоке 10 на место наименьшего элемента (его номер L) запишется первый (т. к. при первом проходе L =1 ), а на место первого элемента – наименьший (он равен V). После этого произойдет возврат управления к заголовку наружного цикла блоку 4. В нем значение счетчика станет равным i = 2. Затем вновь выполняется его тело, но уже для нового значения счетчика i. Теперь с помощью блоков 5-10 отыскивается наименьший элемент массива начиная с номера 2. Затем в блоках 9-10 он займет второе место в массиве и т. д. Когда тело наружного цикла выполнится (N-1), раз массив будет отсортирован.

В блоке 12 отсортированный массив будет выведен и в блоке 13 алгоритм окончит работу.

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

Дан двумерный квадратный массив Z, состоящий из N строк и N столбцов. Необходимо найти среднее арифметическое S его отрицательных элементов и заменить положительные элементы побочной диагонали массива средним арифметическим S.

Блок-схема алгоритма

Блок-схема алгоритма показана на рисунке выше. Она состоит из 13 блоков. В блоке 2 переменная N и весь массив Z заполняются константами. В блоке 3 рабочие переменные S и К получает значение нуль. Переменная S сначала будет играть роль сумматора отрицательных элементов массива, затем после накопления суммы она примет значение среднего арифметического. Переменная К нужна для подсчета количества отрицательных элементов массива.

В блоках 4-7 выполняется накопление суммы отрицательных элементов массива.

Эти блоки образует два вложенных цикла, причем внутренний цикл со счетчиком j является телом наружного цикла со счетчиком i. Проанализируем работу этой структуры.

После входа в наружный цикл в блоке 4 переменная i примет значение i = 1. Далее будет выполнено его тело ( блоки 5-7 ), которое, в свою очередь, также является циклом. После входа во внутренний цикл в блоке 5 переменная j примет значение j = 1. Затем в блоке 6 проверяется на отрицательность элемент массива Z, расположенный в первой строке и первом столбце, т. к. i = 1 и j = 1.

Если он окажется отрицательным, то в блоке 7 переменная К увеличится на 1, а к S добавляется значение этого элемента. После этого выполняется возврат к блоку 5, т. е. к заголовку внутреннего цикла. Здесь j увеличится на 1, станет равной j = 2 и управление перейдет к блоку 6. В нем проверяется элемент, стоящий все в той же первой строке, но во втором столбце (i = 1, j = 2). Если он окажется отрицательным, то К снова увеличится на 1, а к накопленному к этому времени S добавляется значение этого элемента и т.д. Когда полностью выполнится внутренний цикл, т. е. переменная j "пробежит" от 1 до N, в переменную S накопится сумма всех отрицательных элементов первой строки массива, а в К – их количество. Теперь управление передается к блоку 4 заголовка наружного цикла, где i станет равной i = 2. Снова будет отработано его тело, т. е. цикл 5-7. При этом будет найдена уже сумма отрицательных элементов первых двух строк массива, а в К сохранится количество этих элементов. Когда выполнится весь наружный цикл, в S будет константа, равная сумме отрицательных элементов всего массива, а в К – их количество. Теперь управление перейдет к блоку 8. Если окажется, что в массиве есть отрицательные элементы (К>0), то в блоке 9 вычисляется среднее арифметическое как отношение суммы элементов к их количеству. Результат помещается а ту же переменную S. Отметим, что если бы блок 8 проверки отсутствовал, то при К = 0 (в массиве нет ни одного отрицательного элемента) в блоке 9 из-за деления на нуль возникла бы ошибка. Эта ошибка повлекла бы аварийное завершение вычислений до окончания работы алгоритма.

Далее выполняется блоки 10-11, которые также образует цикл. В нем производится замена элементов побочной диагонали на среднее арифметическое S (побочной диагональю является прямолинейная цепочка ячеек в диапазоне от нижнего левого угла до верхнего правого угла массива). Обратите внимание, на то что переменная i, которая использовалась ранее, в целях экономии памяти применяется вновь.

Проследим работу этого цикла. После входа в блок 10 счетчик примет значение i = 1. Затем в блоке 11 при этом значении будет вычислен индекс столбца элемента N – 1 + i = N. Таким образом, элемент с индексами (1, N) станет равным S. На втором круге цикла i увеличится на 1 и станет i = 2. Нетрудно видеть, что теперь элемент (2, N-1) станет равным S и т. д. На последнем круге цикла элемент (N, 1) получит значение S, что завершит изменение значений всех элементов побочной диагонали на среднее арифметическое S.

Наконец, в блоке 12 измененный массив будет выведен и в блоке 13 алгоритм закончит работу.

Перестановки элементов в массиве

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

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

Например, переставим местами первый и второй элементы массива а, используя для временного хранения переменную buf.

buf:=a[1]; а[1]:=а[2]; a[2]:=buf;

В случае перестановки строк матрицы необходимо переставить местами все элементы двух строк.

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

for j:=1 to m do

begin

buf:= a[1,j]; a[1,j]:=a[2,j]; a[2,j]:=buf;

end;

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

Практическая часть

Пример 1. Двумерный массив целых чисел размером 4*3 заполнен случайным образом. Найдите максимальный элемент, а также укажите номер строки и столбца, содержащие этот элемент.

Для решения этой задачи надо выполнить следующие действия:

  • сформировать массив и вывести его элементы на экран;

  • найти максимальный элемент, индекс максимального элемента;

  • вывести максимальный элемент, номер строки и номер столбца максимально элемента.

Составляем или формализуем условие задачи:

Математическая модель.

a) исходные данные:

возьмем a – массив двумерный, n=4 – число строк, m=3 – число столбцов,

Max – максимальный элемент, Imax – номер строки максимального элемента, Jmax – номер столбца максимального элемента. i, j – соответственно индекс строки и индекс столбца.

Алгоритм.

Сначала считаем, что максимальный элемент – Мax есть а[1,1];

Сравниваем этот элемент со всеми остальными элементами массива, начиная с самого себя в цикле. Зачем необходимо сравнивать элемент сам с собой? Дело в том, что, если далее начинать сравнивать Мax в цикле при i=1 и j=2, то элемент 2 строчки и 1 столбца не будет сравниваться с Мax.

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

Почему меньше или равно? Так как сравниваем с самого себя.

На рисунке ниже представлена блок-схема нахождения максимального элемента.

Программа.

Program Maxsimum;

Uses CRT;

const n=4; m=3;

type

Mass=array[1..n,1..m] of integer;

Var

a:Mass;

I, j, Max, Imax, Jmax: integer;

Begin

Clrscr;

Randomize;

for i:=1 to n do

begin

for j:=1 to m do

begin

a[I,j]:=-50+random(101);

write(a[I,j]:4);

end;

writeln;

end;

Max:=a[1,1];

for i:=1 to n do

for j:=1 to m do

if Max:<=a[i,j] then

begin

Max:=a[i,j];

Imax:=i: Jmax:=j:

end;

Writeln(‘Max=’,Max);

Writeln(‘Imax=’,Imax);

Writeln(‘Jmax=’,Jmax);

Readln;

end.

Пример 2. Выделение элементов массива относительно главной диагонали.

uses crt;

const

row=3; { количество строк }

col=row; { количество столбцов }

var

a: array[1..row,1..col]of integer;

b,c: array[1..row*col]of integer;

i,j,n,m: integer;

begin

clrscr; writeln('Введите массив по строкам');

for i:=l to row do

begin

write('строка № ',i,' ') ;

for j:=l to col do read(a[i,j]);

readln;

end;

n:=0; ( количество элементов на главной диагонали и выше }

m:=0; { количество элементов ниже главной диагонали }

for i:= 1 to row do

for j : = 1 to col do

if j>=i then { элемент стоит на главной диагонали и выше }

begin

n:=n+1; { найден еще один элемент }

b[n]:=а[i,j];{ сохранить в массив b под номером n }

end

else { элемент расположен ниже главной диагонали }

begin

m:=m+1; { найден еще один элемент }

c[m] :=a[i,j];{ сохранить в массив с под номером m }

end;

writeln('Элементы на главной диагонали и выше:');

for i:= 1 to n do write(b[i],' '); writeln;

writeln('Элементы ниже главной диагонали:');

for i:= 1 to m do write(с[i],' '); writeln; readln;

end.

Пример 2. Транспонировать матрицу случайных чисел.

const

row=3; col=row;

var

a: array[1..row,1..col] of integer;

i,],buf: integer;

begin

randomize; {инициализация датчика случайных чисел }

writeln('Исходная матрица случайных чисел:');

for i:= 1 to row do

begin

for j:= 1 to col do

begin

a[i,j]:=random(100);{случайное значение элемента }

write (a[i,j]:4); {вывод элемента массива на экран }

end;

writeln;

end;

{транспонирование матрицы }

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

{просмотр элементов в строке, расположенных выше главной диагонали }

for j:=i+1 to col do

{ обмен элементов, симметричных относительно главной диагонали }

begin

buf:=a[i,j]; a[i,j]:=a[j,i]; a[j,i]:=buf;

end;

writeln('Результат транспонирования матрицы:');

for i:= 1 to row do

begin

for j:= 1 to col do write(a[i,j]:4);

writeln;

end;

end.

Задания для самостоятельного выполнения

  1. Ознакомиться с теоретическими сведениями по теме «Двумерные массивы».

  2. Составить программу для обработки двумерного массива в соответствии с вариантом задания, указанного в таблице.

  3. Составить блок-схему решения задачи.

  4. Разработать программу в среде Turbo Pascal 7.0.

  5. Составить систему тестов и проверить работу программу на всех возможных значениях исходных данных.

  6. Ответить на контрольные вопросы.

  7. Результаты выполнения лабораторной работы оформить в виде отчета.

Индивидуальные задания:

Вариант 1. В прямоугольной матрице, размерностью n*m, заполненной случайным образом числами из промежутка [-40,30], найти сумму и количество элементов каждого столбца с заданным условием (хранить эти значения в массивах): элементы, кратные k1 или k2.

Вариант 2. В прямоугольной матрице, размерностью n*m, заполненной случайным образом числами из промежутка [-40,30], найти сумму и количество элементов каждого столбца с заданным условием (хранить эти значения в массивах): элементы, попадающие в промежуток от А до В.

Вариант 3. В прямоугольной матрице, размерностью n*m, заполненной случайным образом числами из промежутка [-40,30], найти сумму и количество элементов каждого столбца с заданным условием (хранить эти значения в массивах): данные элементы положительные и лежат выше главной диагонали.

Вариант 4. В прямоугольной матрице, размерностью n*m, заполненной случайным образом числами из промежутка [-40,30], найти сумму и количество элементов каждого столбца с заданным условием (хранить эти значения в массивах): элементы, которые являются простыми числами.

Вариант 5. Найти сумму элементов в строках с k1-й по k2-ю в прямоугольной матрице, размерностью n*m

Вариант 6. Найти номера всех максимальных элементов в прямоугольной матрице, размерностью n*m.

Вариант 7. Найти номера первых отрицательных элементов каждой строки (столбца) в прямоугольной матрице, размерностью n*m.

Вариант 8. Найти номера последних отрицательных элементов каждой строки (столбца) в прямоугольной матрице, размерностью n*m

Вариант 9. Найти количество элементов в каждой строке, больших (меньших) среднего арифметического элементов заданной строки в прямоугольной матрице, размерностью n*m

Вариант 10. Определить является ли прямоугольная матрица размерностью n*m логическим квадратом, то есть суммы по всем горизонталям, вертикалям и двум диагоналям должны быть равны.

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

Вариант 12. Определить, есть ли в прямоугольной матрице, размерностью n*m строка (столбец), состоящая только из нулевых элементов.

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

Вариант 14. Определить, есть ли в прямоугольной матрице, размерностью n*m строка (столбец), состоящая только из элементов, принадлежащих промежутку от А до В.

Вариант 15. В каждой строке (столбце) прямоугольной матрицы размерностью n*m сменить знак максимального по модулю элемента на противоположный.

Вариант 16. Последний отрицательный элемент каждого столбца в прямоугольной матрице, размерностью n*m заменить нулём.

Вариант 17. В прямоугольной матрице, размерностью n*m положительные элементы умножить на первый элемент соответствующей строки, а отрицательные – на последний, то есть положительные элементы первой строки умножаем на первый элемент первой строки, а отрицательные – на последний элемент также первой строки, то же самое и с остальными строками.

Вариант 18. В прямоугольной матрице, размерностью n*m заменить все элементы строки с номером k и столбца с номером l на противоположные по знаку (элемент стоящий на пересечении, не изменять).

Вариант 19. В прямоугольной матрице, размерностью n*m к элементам столбца k1 прибавить элементы столбца k2.

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

Вариант 21. Заполнить массив А размером n*m следующим образом, например, для n=5 и m=7:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

Вариант 22. Дан двуменый массив B(NM). Получить одномерный массив A,элементы которого равны количеству отрицательных элементов всоответствующем столбце массива B. Найти минимальный элементмассива B.

Вариант 23. Заполнить массив А размером n*m следующим образом, например, для n=4 и m=7:

1

0

2

0

3

0

4

0

5

0

6

0

7

0

8

0

9

0

10

0

11

0

12

0

13

0

14

0

Вариант 24. Определить, является ли данный квадратный массив симметричным относительно своей главной диагонали.{Если массив является симметричным, то для него выполняется равенство a[i,j]=a[j,i] для всех i=l,..., n и j=l,..., n при условии, что i>j. Но если встретится хотя бы одна такая пара, что соответствующие элементы не будут равны, то массив будет несимметричным }

Вариант 25. В прямоугольной матрице, размерностью n*m удалить строку с номером k. {Для того, чтобы удалить строку с номером к, необходимо: - Сдвинуть все строки, начиная с данной, на одну вверх. - Последнюю строку "обнулить", то есть всем элементам последней строки присвоить нулевое значение. Будем выводить на экран сначала все строки, а второй раз, после удаления, на одну меньше.}

Контрольные вопросы

  1. Укажите основные правила организации вложенных циклов.

  2. Как организовать ввод матрицы размером NxM эле­ментов?

  3. Как организовать вывод матрицы в общепринятом виде?

  4. Укажите какие особенности существуют в работе с двумерными массивами по сравнению с одномерными.

  5. Как вывести двумерный массив в виде таблицы?

  6. Можно ли выйти из внутреннего цикла до его окончания?

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