Матрицы (двумерные массивы)
Цель работы: программирование алгоритмов обработки двумерных массивов
Матрица – это прямоугольная таблица элементов (например, чисел или символов). Матрица представляется в виде двумерного массива, то есть массива, все элементы которого имеют два индекса. Матрица, как и таблица, состоит из строк и столбцов. Два индекса элемента — это и есть номера строки и столбца, на пересечении которых этот элемент находится. В языке Си каждый индекс записывается отдельно в квадратных скобках. Каждую строку и каждый столбец матрицы можно рассматривать как обычный одномерный массив. Поэтому можно сказать, что матрица – это массив из массивов.
Первый индекс элемента матрицы – это строка, второй – столбец. Поэтому когда говорят о «матрице 4 на 5», это означает, что матрица имеет 4 строки и 5 столбцов. Матрицы, у которых число строк равно числу столбцов, называют квадратными. В квадратных матрицах можно выделить главную диагональ – это все элементы, у которых номер строки равен номеру столбца, то есть A[0][0], A[1][1], …, A[N-1][N-1] для матрицы размером N на N.
Объявление матриц
Матрицы объявляются так же, как и простые массивы, но у них не один индекс, а два. При объявлении в отдельных квадратных скобках указывается количество строк и количество столбцов. Например, оператор
int B[10][10];
выделит место в памяти под матрицу целых чисел, имеющую 10 строк и 10 столбцов. Если матрица глобальная (объявляется выше всех процедур и функций), то она в самом начале заполняется нулями. Локальные матрицы (объявленные внутри процедуры или функции) первоначально содержат «мусор» – неизвестные значения.
Начальные значения элементов
При объявлении можно сразу задать все или часть ее элементов, например:
float X[2][3] = {{1., 2., 3.},{4., 5., 6.}};
Как видно из примера, элементы каждой строки заключаются в отдельные фигурные скобки. Если задать не все элементы, то остальные заполнятся нулями:
float X[2][3] = {{1., 3.},{6.}};
Здесь элементы X[1][2], X[2][1] и X[2][2] будут нулевыми.
Расположение матриц в памяти
Во всех современных языках программирования элементы матрицы располагаются по строкам, то есть сначала изменяется последний индекс. Объявленная выше матрица X расположена так:
X[0][0] X[0][1] X[0][2] X[1][0] X[1][1] X[1][2]
Стандартный ввод и вывод
Для работы с матрицами требуется вложенный цикл, то есть цикл в цикле.
#include
const int M = 5; // число строк
const int N = 4; // число столбцов
main()
{
int i, j, A[M][N];
for ( i = 0; i M; i ++ ) // цикл по строкам
for ( j = 0; j N; j ++ ) // цикл по столбцам строки (элементы строки)
{
printf (A[%d][%d]=, i, j); // подсказка для ввода
scanf (%d, A[i][j]); // ввод A[i][j]
}
// работа с матрицей
}
Заполнение случайными числами
Выполняется также в двойном цикле аналогично одномерным массивам. В примере показано заполнение целой матрицы случайными числами в интервале [a,b].
for ( i = 0; i M; i ++ )
for ( j = 0; j N; j ++ )
A[i][j] = random(b-a+1) + a;
Вывод на экран
При выводе матрицы ее элементы желательно расположить в привычном виде – по строкам, т.е. вывели одну строку матрицы, перешли на новую строку экрана, и т.д. Надо учитывать, что для красивого вывода на каждый элемент матрицы надо отвести равное количество символов (иначе столбцы будут неровные). Делается это с помощью форматирования – цифра после знака процента задает количество символов, отводимое на данное число.
printf(Матрица A\n);
for ( i = 0; i M; i ++ ) // цикл по строкам
{
for ( j = 0; j N; j ++ ) // вывод одной строки (в цикле)
printf ( %4d, A[i][j] ); // 4 символа на число
printf(\n); // переход на другую строку
}
Алгоритмы для работы с матрицами
Поиск минимального элемента
В отличие от одномерных массивов, для перебора всех элементов матрицы надо использовать двойной цикл. Ниже показано, как найти минимальный элемент в массиве и его индексы. Сначала считаем, что минимальным является элемент A[0][0], а затем проходим все элементы, проверяя, нет ли где еще меньшего. Можно запоминать только индексы, а значение минимального элемента получать прямо из массива.
float A[M][N], i, j, row, col;
…
row = col = 0; // сначала считаем, что A[0][0] — минимальный
for ( i = 0; i M; i ++ ) // просмотр всех строк
for ( j = 0; j N; j ++ ) // просмотр всех столбцов
if ( A[i][j] A[row][col] )
{
row = i; // запомнили новые индексы
col = j;
}
printf (Минимальный элемент A[%d][%d]=%d,row, col, A[row][col]);
Работа с отдельными элементами
Рассмотрим квадратную матрицу N на N. Выведем на экран обе ее диагонали (главную диагональ и перпендикулярную ей). С главной диагональю все просто – в цикле выводим все элементы, у которых номера строки и столбца равны, то есть A[i][i] для всех i от 0 до N-1.
Вторую диагональ формируют такие элементы:
A[0][N-1], A[1][N-2], A[2][N-3], …, A[N-1][0]
Обратим внимание, что каждый следующий элемент имеет номер строки на 1 больше, а номер столбца – на 1 меньше. Таким образом, сумма номеров строки и столбца постоянна и равна N-1. Тогда, зная номер строки i можно сразу сказать, что на второй диагонали стоит ее элемент A[i][N-1-i].