#16 Двумерные и Многомерные массивы в Паскаль

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

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

1 2 4 5
1 3 4 7
8 9 5 6

Или возьмем более вариант с меньшим числом элементов:

1 2 4
8 3 4 

И сразу же напишем для него код:

var
  a: array [1..2, 1..3] of integer;
begin
// сохраняем числа первой строки:
  a[1][1] := 1;
  a[1][2] := 2;
  a[1][3] := 4;
// сохраняем числа второй строки:
  a[2][1] := 8;
  a[2][2] := 3;
  a[2][3] := 4;
// теперь выведем на экран второе число второй строки:
  writeln('a[2][2]=', a[2][2]);
end.  

-- здесь для обращения к конечному элементу двумерного массива (в нашем случае там хранится тип integer), мы сначала указываем индекс его одномерного родительского массива, а потом уже индекс самого элементам в этом родительском массиве по схеме:

имяДумерногоМассива[индексВложенногоМассива][индексЭлементаВМассиве]

, т.е. при обращении:

a[2][2]

-- первая двойка это индекс вложенного массива в двумерном массиве "а", а вторая двойка - уже индекс самого элемента.

Объявления многомерных массивов

Пусть у нас есть массив массивов целых чисел - такой же, как мы рассматривали в примере выше (т.е. фактически двумерный массив целых чисел)

Рассмотри ниже варианты его объявления, записи диапазонов индексов:

  1. Вариант "индексы через запятую":
    -- именно этот способ мы использовали выше:
    var
      a: array [1..2, 1..3] of integer;
    

    -- он довольно наглядный, если знать о чем идет речь.

  2. Варинт "array of array":
    var
      a: array [1..2] of array [1..3] of integer;
    

    -- эта запись больше похожа на "человеческий" язык, но при этом несколько длинее

  3. Также можно комбинировать разные форматы, напр. когда мы хотим отдельно определить вложенный тип:
    type
    // двумерный массив 2 на 4:
      twoArr = array[1..2, 1..4] of integer;
    // трехмерный = одномерный массив двумерных массивов:
      threeArr = array[1..5] of twoArr; 
    var
      a: threeArr;
    

    -- тут мы показываем, используя секцию type (как в одномерных массивах), сначала задали тип двумерного массива "twoArr", а потом указали, что "threeArr" это массив из пяти элементов типа "twoArr".

    Этот вариант может быть полезен, если нам потребуется передавать подмассив в подпрограмму (а значит и описать тип этого подмассива в сигнатуре этой подпрограммы).

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

Примеры кода -- разбор решений

Пример 1 -- обход многомерных массивов

Задача:

Задайте массив целых чисел размерностью 3x4, инициализируйте его случайными числами из диапазона от -5 до 10, после чего выведите значения массива на экран.

Возможное решение (с учетом того, что мы уже умеем писать свои процедуры и функции):

type
  myArr = array[1..3, 1..4] of integer;

// генерация массива
function getArray(): myArr;
var min, max, i, j: integer;
  a: myArr;
begin
   randomize();
   min := -5;
   max := 10;
   for i:=low(a) to high(a) do // по массиву массивов
     for j:=low(a[i]) to high(a[i]) do  // по вложенному массиву
       a[i][j] := min + random(max - min + 1);
   result := a;
end;

// распечатка
procedure printArr(a: myArr);
var i, j: integer;
begin
   for i:=low(a) to high(a) do
   begin
     for j:=low(a[i]) to high(a[i]) do
       write(a[i][j], ' ');
     writeln();
   end;
end;

begin
  printArr(getArray());
end.

Пример №2 -- трехмерный случай ;)

Задайте трехмерный массив целых чисел размерность 3 на 2 на 4 и:
присвойте второму элементу второго подподмассива третьего подмассива в качестве значения число 5

Решение:

type
  threeArr = array[1..3, 1..2, 1..4] of integer;
var
  a:  threeArr;
begin
  a[3][2][2] := 5;
  writeln(a[3][2][2]);

  readln();
end. 

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

  1. Пользователь вводит подряд 8 целых числ, сохраните их в двух разных двумерных массивах:
    • 1) первые 4 числа так, чтобы в каждом подмассиве было 2 элемента.
    • 2) вторые 4 числа так, чтобы в каждом подмассиве было по 1 элементу

    Обойдите эти двумерные массивы и распечатайте результат (значения очередного подмассива печатайте с новой строки)

  2. Вспомогательная задача (можно решить, просто используя одномерные массивы):
    Пользователь вводит 4 целых числа, считаем все их координатами на прямой, а именно:
    • первые два числа - начало и конце отрезка 1
    • вторые два - начало и конец отрезка 2

    Задача: напишите подпрограмму, которая определит пересекаются ли данные отрезки.

  3. Есть функция, которая считает сумму четырех чисел:
    function sum4(a, b, c, d: integer): integer;
    begin
      result := a + b + c + d;
    end;
    

    Реализуйте обертку над sum4(), которая делает то же самое, но имеет сигнатуру вида:

    type ar = array[1..2, 1..2] of integer;
    
    function searchRes2(a1:ar): integer;
    
  4. Вспомогательная задача (можно решить, просто используя одномерные массивы):
    Пользователь вводит 4 целых числа, считаем все их координатами на прямой, а именно:
    • первые два числа - начало и конце отрезка 1
    • вторые два - начало и конец отрезка 2

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

    Примечание: оформить поиск пересечения в виде процедуры, которая получает на вход 4 аргумента целого типа (4 координаты - по две для каждого отрезка) и ещё 2 параметра по ссылке:

    1. одномерный массив из 2 элементов, куда будет записано пересечение (если оно будет найдено)
    2. булево значение, которое показывает найдено ли пересечение
  5. Пользователь вводит N ($N \lt 20$) пар целых чисел, считаем что это пары координат отрезков на прямой, сохраните их в двумерный массив.

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