Лабораторная работа 5. Статические матрицы
Поможем в ✍️ написании учебной работы
Поможем с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой

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

 

Теоретические сведения

Двумерные массивы – матрицы – представляют собой массивы одномерных массивов (таблицы) и задаются двумя числами в квадратных скобках:

тип_элементов имя_массива [размер1] [размер2];

Здесь размер1 – количество строк, размер2 – количество столбцов.

Пример - объявление матриц

double matr1 [100] [10];

int matr2 [10] [20];

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

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

Пример – ввод целочисленной матрицы с клавиатуры

#include <iostream>

const ROW = 5;

const COL = 4;

 

int main ( )

{ int i, j;

int x [ROW][COL];

for (i = 0; i < ROW; i++) // по строкам

{ for (j = 0; j < COL; j++)  // столбцам

    { cout << “x[“ << i << “][“ <<j <<”]”;

        cin >> x[i][j];

     }

  }

return 0;

}

Пример – ввод целочисленной матрицы с помощью генератора случайных чисел

#include <iostream>

#include <iomanip.h>

#include <stdlib.h>

const ROW = 5;

const COL = 4;

 

int main ( )

{ int i, j;

int x [ROW][COL];

for (i = 0; i < ROW; i++) // по строкам

{ for (j = 0; j < COL; j++)  // столбцам

        { x[i][j] = rand ( ) % 10 – 5;

            cout << setw (4) <<x[i] [j];

         }

       cout << endl;

  }

return 0;

}

Вывод матриц тоже происходит с помощью вложенных циклов.

for (i = 0; i < ROW; i++)

{ for (j = 0; j < COL; j++)

   cout << setw(4) << x[i][j];

cout << endl;

}

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

int x [5] [3] = { {1, 2, 3),   // строка первая

                       {4, 5, 6},  // строка вторая

                       {7, 8, 9},  // строка третья

                       {10, 11, 12}, // строка четвертая

                       {13, 14, 15} }; // строка пятая

Типичной ошибкой, не вызывающей сообщения компилятора, является объявление вида:

int m [i, j];  // ошибка

Компилятор воспринимает запятую как операцию “запятая” и игнорирует один из индексов.

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

- работа с матрицей в целом,

- работа со строками или столбцами матрицы,

- работа с диагональными элементами матрицы.

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

Пример – поиск максимального элемента матрицы

int matr [n] [k], max;

        max = matr [0][0];

for (i = 0; i < n; i++)

for (j = 0; j < k; j++)

if (max < matr [i][j]) max = matr [i][j];

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

Пример – поиск максимальных элементов каждой строки матрицы

int matr [n] [k];

int max [n];

for (i = 0; i < n; i++)

           { max[i] = matr [i][0];

for (j = 0; j < k; j++)

if (max[i] < matr [i][j]) max[i] = matr [i][j];

}

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

Работа со столбцами матрицы отличается от работы со строками только тем, что цикл обработки столбцов становится внешним и результирующий массив (строка) имеет размерность, равную количеству столбцов.

Пример – поиск максимальных элементов каждого столбца матрицы

int matr [n] [k];

int max [k];

for (j = 0; j < k; i++)

           { max[j] = matr [0][j];

for (i = 0; i < n; i++)

if (max[j] < matr [i][j]) max[j] = matr [i][j];

}

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

a00 a01…  a04

a10 a11…  a14

а40 a41…  a44

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

Для элементов, стоящих на главной диагонали, выполняется равенство i = j. Если выполняется условие i > j, то элемент находится под главной диагональю, если i < j, то элемент находится над главной диагональю.

Элемент находится на побочной диагонали, если выполняется условие i = n – j – 1. Здесь n – порядок (количество элементов) матрицы.

i > (n – j – 1) – условие нахождения элемента под побочной диагональю.

i < (n – j – 1) – условие нахождения элемента над побочной диагональю.

Пример

Найти среднее арифметическое отрицательных элементов, расположенных под главной диагональю квадратной действительной матрицы 9×9

 

#include <iostream>

#include <iomanip.h>

#include <stdlib.h>

const ROW = 9;

const COL = 9;

int main ( )

{ int i, j, n = 0;

float matr [ROW][COL];

float srednee = 0;

for (i = 0; i < ROW; i++) // по строкам

{  for (j = 0; j < COL; j++)  // столбцам

        { matr[i][j] = (float) rand ( ) % 20 – 10;

            cout << setw (6) <<matr[i] [j];

         }

       cout << endl;

  }

for (i = 0; i < ROW; i++) // по строкам

  { for (j = 0; j < i; j++)

         if (matr[i][j] < 0)

            { n++;

                srednee += matr[i][j];

             }

  srednee = srednee / n;

  cout << endl;

  cout << “Среднее арифметическое = “ << srednee << endl;

return 0;

}

 

Примеры программ со статическими матрицами

Пример 1

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

 

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

 

#include <iostream>

 

using namespace std ;

int main ( )

{

int i ,  j , n;

int a [ 20 ] [ 20 ] ; // описание матрицы

cout <<" n = ";

cin >> n;              //ввод количества строк и столбцов

cout <<"Ввод матрицы a "<< endl ;

for ( i =0; i<n; i++)                       // цикл по строкам

for ( j =0; j<m; j++)                 // цикл по элементам строки

     cin >> a [ i ] [ j ] ;                    

 

// работа с матрицей

int s = 0;

for ( i =0; i<n ; i++)

for ( j =0; j < n; j++)

// если элемент лежит выше главной диагонали, то наращиваем сумму

     i f ( j > i )  s+=a [ i ] [ j ] ;

cout<<" S = "<<s<<endl ;

return 0;

}

 

Пример 2

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

 

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

Будем считать, что матрица a имеет размер [n*n].

Элементы первой строки матрицы a можно представить как a[0][ i], где i меняется от 0 до n,

элементы последней строки - a[ n-1, 0],

элементы первого столбца – a[ i, 0].

элементы последнего столбца – a[ i, n-1],

элементы главной диагонали – a[ i, i],

элементы побочной диагонали – a[ i, n- i -1]

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

 

 #include <iostream>

 

using namespace std ;

int main ( )

{

int i ,  j , n, k;

int a [ 20 ] [ 20 ] ; // описание матрицы

cout <<" n = " ;

cin >> n;              //ввод количества строк и столбцов

 

cout <<"Ввод матрицы a "<< endl ;

for ( i =0; i<n; i++)                       // цикл по строкам

for ( j =0; j<n; j++)                 // цикл по элементам строки

     cin >> a [ i ] [ j ] ;                    

//k - количество положительных элементов матрицы,

// расположенных по её периметру и на диагоналях.

for ( i=0, k=0; i<n; i++)

{

  if  (a [ i ] [ i ] > 0) k = k+1;                    // элемент лежит на главной диагонали

  if  (a [ i ] [n−i −1] > 0) k = k+1;                // элемент лежит на побочной диагонали

}

for  ( i =1; i<n−1; i++)

{

if  (a [ 0 ] [ i ] > 0) k = k+1;                          // элемент находится в нулевой строке

if  (a [n−1] [ i ] > 0) k++;                           // элемент находится в последней строке

if  (a [ i ] [ 0 ] > 0 )     k++;                                  // элемент находится в нулевом столбце

if  (a [ i ] [n−1] > 0) k++;                             // элемент находится в последнем столбце

}

// элемент, находящийся на пересечении диагоналей, возможно, подсчитан дважды,

// надо уменьшить вычисленное значение k на один

if ( (n%2 != 0) && (a [n/ 2] [n/2] > 0) ) k = k-1;

cout<<" k = "<<k<<endl ;

return 0;

}

Пример 3

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

 

Для решения задачи нужно найти в каждой строке матрицы сумму элементов и разделить ее на количество элементов в строке. Затем полученное число записать в нулевой элемент соответствующей строки.

 

#include <iostream>

#include <iomanip>  // библиотека манипуляторов

 

using namespace std ;

int main ( )

{

int i ,  j , n, m;

float a [ 20 ] [ 20 ] ; // описание матрицы

cout <<" n = " ;

cin >> n;              //ввод количества строк

cout << " m = " ;

cin >> m;             //ввод количества столбцов

 

cout <<"Ввод матрицы a "<< endl ;

for ( i =0; i<n; i++)                       // цикл по строкам

for ( j =0; j<m; j++)                // цикл по столбцам

     cin >> a [ i ] [ j ] ;                    

 

// работа с матрицей

float S = 0;

for ( i =0; i<n; i++)                       // цикл по строкам

{

    for ( j =0; j<m; j++)                // цикл по столбцам

       S = S + a[ i ] [ j ] ;

// когда строка просмотрена, надо найти среднее арифметическое и записать его в начало строки

   a[ i ] [ 0 ] = S / m;

// переходим на новую строку (новая итерация внешнего цикла)

}

// преобразованная матрица

for ( i =0; i<n; i++)                        // цикл по переменной i, перебираем строки матрицы

{

for ( j =0; j<m; j++)                       // цикл по переменной j, перебираем элементы внутри строки

      cout << setw(5) << a [ i ] [ j ] ;   // вывод очередного элемента матрицы

cout<<endl ;                       // после вывода всех элементов строки  переходим на новую строку

}

 return 0;

}

 

Пример 4

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

 

Для решения этой задачи надо найти минимальный элемент матрицы (min) и его индексы imin и jmin, а также максимальный элемент (max) и его индексы imax и jmax. Затем надо поменять местами элементы a[ imin ][ jmin ] и a[ imax ][ jmax ], для этого надо ввести вспомогательную переменную.

Чтобы найти минимум во всей матрице, в переменную min запишем значение a[0][0], в переменную imin и в переменную jmin (номер строки и столбца, где находится минимальный элемент) запишем нули. Затем в двойном цикле сравниваем каждый элемент матрицы с минимальным (переменная min). Если какой-то элемент окажется меньше, чем min, записываем его в переменную min, а в переменную imin – текущее значение индекса i, в переменную jmin – текущее значение индекса j. Поиск максимального элемента матрицы аналогичен, только сравнение будет другое.

#include <iostream>

#include <iomanip>  // библиотека манипуляторов

 

using namespace std ;

int main ( )

{

int i ,  j , n, m;

int a [ 20 ] [ 20 ] ; // описание матрицы

cout <<" n = " ;

cin >> n;              //ввод количества строк

cout << " m = " ;

cin >> m;             //ввод количества столбцов

cout <<"Ввод матрицы a "<< endl ;

for ( i =0; i<n; i++)                       // цикл по строкам

for ( j =0; j<m; j++)                // цикл по столбцам

     cin >> a [ i ] [ j ] ;                    

 

// работа с матрицей

int min, max, imin. imax, jmin, jmax;

min = a[0][0]; max = a[0][0];

imin = 0; jmin = 0;

imax =0; jmax = 0;

for ( i =0; i<n; i++)                       // цикл по строкам

for ( j =0; j<m; j++)                     // цикл по столбцам

{ if  (a[i][j] < min)

          { min = a[i][j];

             imin = i;

             jmin = j;

           }

         if  (a[i][j] > max)

          { max = a[i][j];

             imax = i;

             jmax = j;

           }

      }

// меняем местами

int b;

b = a[ ima][jmax];

a[ imax ][ jmax ] = a[ imin ][jmin ];

a[imin][jmin] = b;

 

// преобразованная матрица

for ( i =0; i<n; i++)                        // цикл по переменной i, перебираем строки матрицы

{

for ( j =0; j<m; j++)                       // цикл по переменной j, перебираем элементы внутри строки

      cout << setw(5) << a [ i ] [ j ] ;   // вывод очередного элемента матрицы

cout<<endl ;                       // после вывода всех элементов строки  переходим на новую строку

}

 return 0;

}

Пример 5

Проверить, является ли заданная матрица единичной.

 

Квадратная матрица называется единичной, если по ее главной диагонали записаны единицы, а все остальные элементы матрицы нулевые.

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

 

#include <iostream>

 

using namespace std ;

int main ( )

{

int i ,  j , n;

int a [ 20 ] [ 20 ] ; // описание матрицы

cout <<" n = ";

cin >> n;              //ввод количества строк и столбцов

cout <<"Ввод матрицы a "<< endl ;

for ( i =0; i<n; i++)                       // цикл по строкам

for ( j =0; j<m; j++)                 // цикл по элементам строки

     cin >> a [ i ] [ j ] ;                    

 

// предположим, что матрица единичная и запишем в некоторой переменной pr единицу.

//  Если значение этой переменной не изменится по выходу из цикла, то матрица единичная

 int pr =1;

 for ( i =0; i<n; i++)                       // цикл по строкам

for ( j =0; j<n; j++)                 // цикл по элементам строки

   if ((( i == j) && (a[i][j] != 1)) || ((i != j) && (a[i][j] != 0)))

      { pr = 0;

          break; // матрица не является единичной, выходим из цикла

       }

if (pr == 1)

cout << “Матрица является единичной”;

else cout << “Матрица единичной не является”;

return 0;

}  

 

Порядок выполнения работы

Построить алгоритм решения задачи и написать программу согласно вариантам заданий.

 

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

1. Как объявить матрицу в программе на С++?

2. Как индексируются элементы матрицы в языке С++?

3. Что такое главная и побочная диагонали в матрице?

4. Каким образом можно объявить трехмерный массив в С++ программе?

 

Содержание отчета

1. Титульный лист отчета

2. Запись алгоритма решения задачи

3. Текст программы на языке С++

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

Дата: 2019-04-23, просмотров: 159.