Матрица из N строк и N столбцов

Лабораторная работа №9.

Тема: Обработка одномерных и двумерных массивов.

Цель: Развить навыки обработки одномерных и двумерных массивов. Уметь использовать различные методы описания массивов и сортировки массивов.

Оборудование и материалы: Методическое пособие, ПЭВМ, ручка, карандаш, линейка, ластик, шаблон А4.

Ход работы

Методические рекомендации.

Необходимая информация содержится в лекции № 12.

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

Задание для лабораторной работы выбрать согласно варианту по приведённой таблице. Вариант определяется порядковым номером в журнале группы.

! Внимательно изучите алгоритм пузырьковой сортировки.

!! Рассмотрите подробно задачу №2. В ней рассмотрены алгоритмы генерации различного числа наборов данных.

Образцы решения типовых задач.

Рассмотрим алгоритм пузырьковой сортировки.

Сравним первый элемент массива со вторым. Если первый окажется больше второго, то поменяем их местами. Те же действия выполним для второго и третьего, третьего и четвертого, I-го и (I + 1)-го, (n - 1)-го и n-го элементов. В результате этих действий самый большой элемент станет на последнее (n-e) место. Теперь повторим данный алгоритм сначала, но последний (n-й) элемент, рассматривать не будем, так как он уже занял свое место. После проведения данной операции самый большой элемент оставшегося массива встанет на (n - 1)-е место. Так повторяем до тех пор, пока не упорядочим весь массив.

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

 

Процесс упорядочивания элементов в массиве по возрастанию представим в таблице:

 

  Номер элемента
         
Исходный массив          
Первый просмотр          
Второй просмотр          
Третий просмотр          
Четвертый просмотр          

 

Листинг программы упорядочивания элементов в массиве по возрастанию их значений.

Var

i, n, j: integer;

b:word;

y: array [1.. 100] of word;

Begin

writeln ('введите размер массива');

readln (n);

for i:=1 to n do

Begin

write ('y[', I, ']=');

readln (y[i]);

end;

writeln ('массив y');

for i:=1 to n dowrite (y [ i ], ' ');

writeln;

for j:=1 to n-1 do

for i:=1 to n-j do

if y[ i ] > y [i + 1] then { Если текущий элемент больше следующего, то }

begin {поменять их местами. }

b:=y[ i ]; { Сохранит значение текущего элемента. }

y[ i ]:=y[i + 1]; { Заменить текущий элемент следующим. }

у[i + 1]:=b; { Заменить следующий элемент текущим. }

end;

writeln ('упорядоченный массив');

for i:=1 to n do

write (y[ i ], ' ');

writeln;

End.

Пример 2. Разработать программу генерации следующих комбина­ций: 1111, 1112, 1113, 1121, 1122, 1123, 1131, 1132, 1133, 1211,..., 3333.

Вариант 1. Для генерации комбинаций используем вложенные цик­лы. Количество разрядов - 4. Следовательно, для генерации всех комбинаций понадобится 4 цикла, вложенных один в другой (рис. а). Если ввести параметр m - максимальное значение в каждом разряде, то эта же програм­ма будет генерировать комбинации от 1111 до mmmm.

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

Вариант 2. С точки зрения увеличения универсальности программы для генерации всех комбинаций лучше использовать программно реализуе­мый счетчик в общем случае на n разрядов, который в каждом разряде счи­тает от 1 до n. Каждое состояние такого счетчика соответствует комбинации. Для генерации следующего варианта в младший разряд счетчика добавляют 1 и осуществляют межразрядные переносы в соответствии с характеристика­ми каждого разряда.

Ниже представлена программа, реализую­щая данный алгоритм для n < 10.

 

 

               
   
 
     
     
 
 
 

 

 


 

 
 
a[n]=a[n]+1


 

 

                   
   
 
   
 
   
a[i-1]= a[i-1]+1
 
   
 
 

 


Два варианта алгоритма генерации комбинаций:

а - с использованием вложенных циклов; б - программно реализуемый счетчик.

 

Program ex2;

Const

a:array[1..10] of byte=(l, 1,1,1,1,1,1,1,1,1);

var i,m,n:integer;

Begin

readLn (n,m);

while a[ 1 ]<m +1 do {условие «сброса» счетчика}

begin

for i:=l to n do write (a[i]); {вывод комбинации}

write (' ');

a[n]:=a[n]+l; {добавление 1 в последний разряд}

for i:=n downto 2 do {анализ и осуществление переносов}

if a[i]>m then

Begin

a[i]:=1;

a[i-1]:=a[i-1]+1;

end;

end;

End.

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

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

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

Ограниченный перебор, реализованный с использованием рекурсии. Для генерации комбинаций будем использовать древовидную рекурсию, на каж­дом уровне которой ставится один ферзь m различными способами. При этом появляется возможность проверки перспективности уже имеющейся комбинации. Поясним сказанное на примере доски 4x4.

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

1..., 2...,3...,4....

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

11.., 12.., 13., 14.. 21., 22.., 23., 24.. 31., 32., 33., 34.. 41., 42., 43., 44..

На этом этапе уже можно исключить все варианты, для которых первые два ферзя бьют друг друга: 11., 12., 21., 22., 23., 32., 33., 34., 43., 44.. Ге­нерацию остальных комбинаций необходимо продолжить, установив третье­го ферзя одним из четырех способов и исключив неперспективные решения. На последнем этапе необходимо установить четвертого ферзя и опять исключить варианты, в которых ферзи бьют друг друга. Оставшиеся варианты яв­ляются решениями задачи.

На рисункке показан фрагмент дерева генерации вариантов для m = 4 с отсечением неперспективных ветвей. Первое найденное решение - комбина­ция 2413.

 
 

 

 


1421 1422 1423 1424 2411 2412 2413 2414

Program ex21;

Type p=array[l..100] of integer;

Var

Pole: p;

k,m: integer;

{функция проверки перспективности комбинации}

function new_r(n:integer;pole:p):boolean;

var j: integer;

begin

new _ r:=false;

for j:=l to n-1 do

if (pole[j]=pole[n]) or (abs(pole[j]-pole[n])=n-j) then exit;

new _r:-true;

End;

 

{рекурсивная функция генерации комбинации }

procedure ferz (n,m:integer; var pole.p);

var i.integer;

begin

if n=m+l then {если установлено m ферзей, то вывести решение}

begin

for i:=l to m do write (polefi]:2);

writeln;

end

else {иначе - пытаемся установить следующего ферзя}

for i:=l to m do {m способами}

Begin

pole[n]:=i; {установка n-го ферзя}

if new_r(n,pole) {проверка перспективности комбинации}

thenferz (n+l,m,pole); {рекурсивный вызов установки

следующего ферзя}

end;

end;

{основная программа}

Begin

writeLn ('Введите размер доски:');

readLn (m);

к:=0;

ferz(l,m,pole);

End.

Размер доски Количество вариантов, которое проверяется при полном переборе Количество вариантов, рассмотренных при ограниченном переборе Количество полученных решений
4x4 44 = 256    
5x5 55 = 3125    
6x6 б6 = 46656    
7x7 77 = 823543    
8x8 88= 16777216    

Пример 3. Задан массив из n элементов. Сформировать массивы номеров положительных и отрицательных элементов.

program mas_six;

Type

massiv= array [1..20] of real;

massiv= array [1..20] of integer;

Var

a,s: massiv1;

y: massiv;

i,k,l,n: integer;

Begin

write (‘n=’);

readln (n);

for i:=1 to n do

Begin

write (‘y[‘,i,’]=’);

readln (y[i]);

end;

k:=0; {счетчик положительных элементов.} l:=0; {счетчик отрицательных элементов.} for i:=1 to n do begin if y[i]>o then {если элемент положительный, то} begin {нарастить счетчик k на 1 и} k:=k+1; {записать номер элемента в массив S} s[k]:=I; end; if y[i]<0 then {если элемент отрицательный, то} begin l:=l+1; {записать номер элемента в массив А} a[l]:=i; end; end; writeln (‘массив индексов положительных элементов’); for i:=1 to k do write (s[i],’ ‘); writeln; writeln (‘массив индексов отрицательных элементов’); for i:=1 to l do write (a[i],’ ‘); writeln; end.  

 

 


Пример 4. Задан массив y из n целых чисел. Сформировать массив z таким образом, чтобы вначале шли отрицательные элементы массива y, затем положительные и наконец нулевые.

program ex4;

Var

Y, z: array [1…50] of integer;

I, k, n: integer;

Begin

writeln (‘введите n<=50’)

readln (n);

for i: =1 to n do

Begin

write (‘y [‘, I,’] =’);

readln (y [i]);

end;

k:=0;

for i:=1 to n do

if y [i] < 0 then

begin

k:=k+1;

z [k]: = y [i];

end;

for i:=1 to n do

if y [i] > 0 then

Begin

k:=k+1;

z [k]: = y [i];

end;

for i:=1 to n do

if y [i] = 0 then

Begin

k:=k+1;

z [k]: = y [i];

end;

 

 

Пример 5. Переписать элементы массива х в обратном порядке. Блок-схема Представлена на рис.4.7. Алгоритм состоит в следующем: меняем местами 1-й и n-й элемент, затем 2-й и (n-1)-й и т.д. середины массива (элемент с номером I следует обменять с элементом (n+1-i)).

program mas_5;

type

massiv= array [1..100] of real;

Var

x:massiv;

i, n: integer;

b: real;

Begin

writeln (‘введите размер массива’);

readln (n);

for i:=1 to n do

Begin

write (‘x[‘,i,’]=’);

readln (x [ i ]);

end;

{Элементы массива меняются местами: 1- й – с n-м,2-й- с (n-1) и т.д.}

for i:=1 to n div 2 do

Begin

b:=x[n+1-i];

x[n+1-i ]:=x[i];

x[i]:=b;

end;

writeln (‘ преобразованный массив’);

for i:=1 to n do

write (x [i]:1:2,’’);

end.

 

Пример 6. Найти сумму элементов матрицы, лежащих выше главной диагонали.

Алгоритм решения главной задачи построен следующим образом: обнуляется ячейка для накапливания суммы (переменная s).Затем с помощью двух циклом(первый по строкам, второй по столбцам) просматривается каждый элемент матрицы, но суммирование происходит только в том случае, если этот элемент находится выше главной диагонали, то есть выполняется свойство i<j.

program ex6;

Var

a: array [1..15,1..10] of real;

i,j,n,m: integer;

s: real;

Begin

writeln (‘ введите размеры матрицы’);

writeln (‘n-количество строк, m-количество столбцов’);

readln (n,m);

for i:=1 to n do

for j:=1 to m do

Begin

write (‘a[‘,i, ‘, ‘, j, ‘ ]=’);

 

readln (a[i,j]);

end;

S:=0;

for i:=1 to n do

for j:=1 to n do

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

s:=s+a [i,j]; {наращиваем сумму. }

writeln (‘матрица А’);

for i:=1 to m do

{Здесь важен формат, особенно общая ширина поля! }

write (a[i, j]:8:3, ‘ ‘);

Writeln

end;

writeln (‘сумма элементов матрицы’, s:8:3);

End.

 

Пример 7. преобразовать матрицу А (m,n) так, чтобы строки были упорядочены по убыванию, с четными – по возрастанию.

 

program ex7;

Var

a: array [1...15,1..15] of real;

j, i. k. m, n: byte;

b: real;

Begin

writeln (‘введите m и n’);

readln (m,n);

for i:=1 to m do

for j:=1 to n do

begin

write (‘a[‘,I,’,’,j,’] =’);

readln (a[i,j]);

end;

writeln (‘матрица а’);

for i:=1 to m do

Begin

for j:=1 to n do

write (a[I,j]:7:3,’ ‘);

writeln;

end;

for i:=1 to m do

if (I mod 2)=0 then {если номер строки четный, то упорядочить ее элементы по

возрастанию.}

begin

for k:1 to n-1 do

for j:1 to n-k do

if a[i,j] >a[i,j+1] then

begin

b:=a[i,j];

a [i,j]:=a [i,j+1];

a[I,j+1]:=b;

end;

end;

else {если номер строки нечетный, то упорядочить ее элементы по убыванию.}

for k:=1 to n-1 do

for j:=1 to n-k do

if a[I;j]< a[i,j+1] then

Begin

b:=a[I,j];

a[i,j]:=a [i,j+1];

a[I,j+1]:=b;

end;

writeln (‘преобразованная марица а);

for i:=1 to m do

Begin

for j:=1 to m do

write (a [I,j]:7:3,’ ‘);

writeln;

end;

End.

 

Пример 8. Написать программу умножения двух матриц A(n, m) и B(m, l).Например, необходимо перемножить две матрицы:

Воспользуемся правилом «строка на столбец», получим матрицу

В общем виде формула для нахождения элемента матрицы выглядит следующим образом:

= ,

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

Var

Begin

writeln

readln

for to d o

begin

write (‘a[‘, i,’,’,j,’]=’);

readln (a[i, j]);

end;

for i:=1 to m do

for j:=1 to 1 do

Begin

write (‘b[‘, i, ’,’,j,’]=’);

readln (b[I,j]);

end;

for i:=1 to n do

for j:=1 to l do

begin

{В переменной S будет храниться результат скалярного произведения i-й строки на j- й столбец.}

S:=0;

for k:=1 to m do s:=s+a[I,k]*b[k,j];

c[I,j]:=s;

end;

writeln (‘Матрица а’);

for i:=1 to n do

Begin

for j:=1 to m do writeln (a[I, j]:7:3,’ ‘);

writeln;

end;

writeln (‘Матрица b’);

for i:=1 to m do

Begin

for j:=1 to l do write (b[i, j]:7:3,’ ’);

writeln;

end;

writeln (‘Матрица с=a*b’);

for i:=1 to n do

begin

for j:=1 to l do write (c[I,j]:7:3,’ ‘);

writeln;

end;

End.

 

Пример.9. Поменять местами n-й и 1-й столбцы матрицы A(k,m).

 

program ex9;

Type

matrica = array of real;

Var

a: matrica;

i, j, k, m, n, l:byte;

b: real;

Begin

write (‘k=’);

readln (k);

write (‘m=’);

readln (m);

for i:=1 to k do

for j:=1 to m do

Begin

write (‘a =’);

readln (a )

end;

Repeat

write (‘n=’);

readln (n);

write (‘l=’);

readln (l);

until (n<=m) and (l<=m) and (n<=l); {Ввод считается верным, если n и l меньше m и не верны друг другу.}

 

for I:=1 to k do {Элементы столбца с номером 1 заменить элементами столбца с номером n.}

Begin

b:=a[i,n];

a[i,n]:= a[i,l];

a[i,l]:=b

end;

for I:=1 to k do

Begin

for j:=1 to m do write (‘a :7:3,’ ‘);

writeln;

end;

End.

 

Пример 10. Преобразовать матрицу A (m,n) таким образом, чтобы каждый столбец был упорядочен по убыванию. Алгоритм решения этой задачи сводится к тому, что уже известный нам по предыдущей главе алгоритм упорядочивания элементов в массиве выполняется для каждого столбца матрицы.

 

program ex10;

Type

matrica = array [1..15,1..15] of real;

Var

a: matrica;

I,j,k,m,n: byte;

b: real;

Begin

write (‘m=’);

readln (m);

write (‘n=’);

readln (n);

for i:=1 to m do

for j: =1 to n do

begin

write (‘a[‘,i,’,’,j,’] =’);

readln (a[I,j]);

end;

writeln (‘матрица a’);

for i:=1 to m do

begin

for j:=1 to n dowrite (a[I, j]:7:3, ‘ ‘);

writeln;

end;

for j: =1 to n do {j- номер столбца.}

for k: =1 to m-1 do {k- номер просмотра.}

for i: =1 to m-k do {I – номер строки.}

 

 

if a [I,j] <a [i+1,j] then

Begin

b: = [a, j];

a [I,j]:=a[i+1,j];

a [i+1,j]:=b;

end;

writeln (‘ преобразованная матрица a’);

for i:= to n do

Begin

for j:= to n do write (a[I,j]:7:3, ‘ ‘);

writeln;

end;

end.

 

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

Прежде чем преступить к решению задачи, обратимся к рис.1, на котором изображена схема квадратных матриц различной размерности. Из условия задачи понятно, что рассматривать все элементы заданной матрицы не нужно. Достаточно просмотреть первую и последнюю строки, первый и последний столбцы, а также диагонали. Все эти элементы отмечены на схеме, причем черным цветом выделены те, обращение к которым может произойти дважды. Например, элемент с номером (1,1) принадлежит как к первой строке, так и к первому столбцу, а элемент с номером (N,N) находится в последней строке и последнем столбце одновременно. Кроме того, если N- число нечетное (на рис.5.7 эта матрица расположена слева), то существует элемент с номером (N div 2+1,N div 2+1), который находится на пересечении главной и побочной диагоналей. При нечетном значении N диагонали не пересекаются.

Матрица из N строк и N столбцов

 

                 
                 
                 
                 
                 
                 
                 
                 
                 
               
               
               
               
               
               
               
               

 

Рис. 1. N - нечетное N - четное

 

 

Для обращения к элементам главной диагонали вспомним, что номера их строк всегда равны номерам столбцов. Так как параметр i изменяется циклически от 1 до N, то - элемент главной диагонали. Воспользовавшись свойством, характерным для элементов побочной диагонали, получим: i+j-1=n j=n-i+1, следовательно, для i=1,2,….,n элемент - элемент побочной диагонали. Элементы, находящиеся по периметру матрицы, записываются следующим образом: - первая строка, - последняя строка, и соответственно - первый столбец, -последний столбец.

 

Рассмотрим блок –схему задачи. В блоке 1 организуется цикл для обращения к диагональным элементам матрицы. Причем в блоках 2-3 подчитывается количество положительных элементов на главной диагонали, а в блоках 5-6- на побочной. Цикл в блоке 6 задает изменение параметра I от 2 до N-1. Это необходимо для того, чтобы не обращаться к элементам, которые уже были рассмотрены: , , и . Блоки 7-8 подчитывают положительные элементы в первой строке, 9 и 10- в последней; 11 и 12- в первом столбце, а 13 и 14- в последнем. Блок 15 проверяет, не был ли элемент, находящийся на пересечении диагоналей, подчитан дважды. Напомним, что это могло произойти только в том случае, если N является нечетным числом и этот элемент был положительным. Эти условия и проверяются в блоке 16, который уменьшает вычисленное количество положительных элементов на единицу.

 

 

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

I, j, n, k: integer;

Begin

write (‘n=’); readln (n);

for i:= 1 to n do

for j:=1 to n do

readln (a[ i, j ]);

writeln (‘ Была введена матрица: ‘);

for i:=1 to n do

begin

for j:=1 to n do write (a[ i, j], ’ ‘);

writeln;

end;

k:=0;

for i:=1 to n do

Begin

if (a[ i, i ]>0) then k:=k+1; { Элемент лежит на главной диагонали}

if a[ i, n-i+1 ]>0 then k:=k+1; { Элемент лежит на побочной диагонали}

end;

for i:=2 to n-1 do

begin

If (a[ 1,i ]>0) then k:=k+1; {Элемент находится в первой строке}

If (a[ n,i ]>0) then k:=k+1; {Элемент находится в последней строке}

If (a[i,1]>0) then k:=k+1; {Элемент находится в первом столбце}

If (a[i,n]>0) then k:=k+1; {Элемент находится в последнем столбце}

end;

{Если элемент, находящийся на пересечении диагоналей, подчитан дважды, то уменьшить k на единицу}

if (n mod 2 <> 0) and (a[(n div 2)+1, (n div 2)+1]>0) then k:=k-1;

write (k); end.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow