Двумерные массивы и матрицы

Урок вводит двумерные массивы (матрицы) — таблицы данных со строками и столбцами — и учит их заполнять, выводить и обрабатывать.

Двумерный массив (матрица) — это таблица значений, где у каждого элемента два индекса: номер строки и номер столбца.

Зачем нужны двумерные массивы

Обычный массив — это ряд ячеек, как один этаж в доме. Но многие данные естественно укладываются в таблицу: оценки учеников по предметам (строки — ученики, столбцы — предметы), пиксели картинки, игровое поле «крестиков-ноликов», расписание. Для таких данных нужен двумерный массив — сетка из строк и столбцов. Это как многоэтажный дом: чтобы найти квартиру, нужны и номер этажа, и номер квартиры на этаже.

Двумерные массивы математики называют матрицами, и это слово вы встретите в учебниках. Не пугайтесь: это просто таблица чисел.

Объявление матрицы

Двумерный массив объявляют, указав два диапазона индексов — для строк и для столбцов:

var
  m: array[1..3, 1..4] of integer;   // 3 строки, 4 столбца

Запись array[1..3, 1..4] читается так: «таблица из 3 строк и 4 столбцов целых чисел». Всего в ней 3·4 = 12 ячеек. Первый диапазон — строки, второй — столбцы (так принято читать). К каждой ячейке обращаются по двум индексам: m[2, 3] — элемент во 2-й строке и 3-м столбце.

begin
  m[1, 1] := 5;     // верхний левый угол
  m[2, 3] := 17;    // строка 2, столбец 3
  m[3, 4] := 9;     // нижний правый угол
end.

Заполнение и вывод: два вложенных цикла

Раз у элемента два индекса, для перебора всей таблицы нужны два вложенных цикла: внешний идёт по строкам, внутренний — по столбцам. Это главный приём работы с матрицами. Заполним таблицу значениями «номер строки умножить на номер столбца» — получится таблица умножения:

rows, cols = 3, 4
m = [[0] * (cols + 1) for _ in range(rows + 1)]  # индексы с 1
for i in range(1, rows + 1):       # по строкам
    for j in range(1, cols + 1):   # по столбцам
        m[i][j] = i * j
# вывод в виде таблицы
for i in range(1, rows + 1):
    for j in range(1, cols + 1):
        print(m[i][j], end='\t')   # табуляция между числами
    print()                         # перенос строки после каждой строки

Вывод:

1	2	3	4	
2	4	6	8	
3	6	9	12	

Запомните ключевую идею вывода: внутренний цикл печатает одну строку таблицы (без перехода, через write и пробел/табуляцию), а после внутреннего цикла ставят writeln, чтобы перейти на новую строку таблицы. Без этого writeln вся матрица «слипнется» в одну линию. На Паскале: внешний for i := 1 to 3, внутри for j := 1 to 4 do write(m[i, j], ' '), а после внутреннего — writeln.

Сумма всех элементов

Чтобы сложить все элементы матрицы, применяем знакомый шаблон накопления, но с двумя циклами:

m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
sum = 0
for i in range(3):
    for j in range(3):
        sum = sum + m[i][j]
print('Сумма всех элементов:', sum)

Вывод:

Сумма всех элементов: 45

Главная диагональ

В квадратной матрице (где строк столько же, сколько столбцов) главная диагональ — это элементы, у которых номер строки равен номеру столбца: m[1,1], m[2,2], m[3,3]. Чтобы пройти по ней, нужен всего один цикл с одинаковым индексом для строки и столбца:

m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
diag = 0
for i in range(3):
    diag = diag + m[i][i]   # оба индекса одинаковы
print('Сумма главной диагонали:', diag)

Вывод:

Сумма главной диагонали: 15

Здесь складываются 1 + 5 + 9 = 15. Побочная диагональ (из правого верхнего угла в левый нижний) задаётся условием j = N + 1 - i — полезное упражнение для самопроверки.

Попробуй сам

Дана матрица 3×3 из чисел от 1 до 9. Найдите сумму элементов первого столбца (то есть m[i, 1] для всех строк). Понадобится один цикл по строкам с фиксированным вторым индексом. Проверьте на Python:

m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
col_sum = 0
for i in range(3):
    col_sum = col_sum + m[i][0]   # первый столбец (индекс 0 в Python)
print('Сумма первого столбца:', col_sum)

Вывод:

Сумма первого столбца: 12

Частые ошибки

  • Перепутали строки и столбцы. В m[i, j] первый индекс — строка, второй — столбец. Перестановка даёт обращение к другой ячейке (а в неквадратной матрице — и выход за границы).
  • Забыли writeln после внутреннего цикла. Без него вся таблица выведется в одну строку. Перенос строки ставят после прохода по столбцам.
  • Один цикл вместо двух. Для полного перебора матрицы нужны два вложенных цикла; один цикл годится только для диагонали или одной строки/столбца.
  • Выход за границы по одному из измерений. Оба индекса должны попадать в свои диапазоны.

Итоги

  • Двумерный массив (матрица) — таблица с двумя индексами: строка и столбец; объявляется как array[1..R, 1..C] of тип.
  • К элементу обращаются двумя индексами: m[строка, столбец].
  • Для перебора всей матрицы нужны два вложенных цикла; вывод требует writeln после каждой строки.
  • Сумма всех элементов — накопление в двух циклах; главная диагональ (m[i, i]) обходится одним циклом.
  • Первый индекс — всегда строка, второй — столбец; не путайте их порядок.
Проверьте себя
1. Как объявить матрицу из 3 строк и 5 столбцов целых чисел?
Aarray[1..3] of integer
Barray[1..3, 1..5] of integer
Carray[1..15] of integer
Darray[3, 5] integer
2. Сколько вложенных циклов нужно для перебора всех элементов матрицы?
AОдин
BДва
CТри
DЗависит от размера
3. Почему после внутреннего цикла при выводе матрицы ставят writeln?
AЧтобы ускорить вывод
BЧтобы перейти на новую строку и таблица не слиплась в одну линию
CЧтобы обнулить строку матрицы
Dwriteln здесь не нужен
Поддержать проект