Теоретический материал (Паскаль)

Работа с элементами массива

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

Нахождение количества элементов с данным свойством

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

Задача 1. Найти максимальный элемент массива и его индексы.

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

Procedure Maximum(X : MyArray2; n, m : integer; Var Max, Maxi, Maxj : integer);
Var
  i, j : integer;
Begin
  Max := X[1, 1]; {Предположим, что максимумом является первый элемент}
  Maxi := 1; {в этом случае запомним первую строку}
  Maxj := 1; {и первый столбец}
  for i := 1 to n do
    for j := 1 to m do
      if X[i, j] > Max {если среди элементов массива нашелся больший элемент, то}
        then
          begin
            Max := X[i, j];{внесем новое найденное значение в переменную Мах}
            Maxi := i; {и не забудем запомнить индексы строки} 
            Maxj := j;      {и столбца этого элемента}
          end;
End;

Задача 2. Найти количество отрицательных элементов в каждой строке.

Рассмотрим несколько способов решения этой задачи.

Способ 1 - количество элементов каждой строки хранить в одномерном массиве (Y) соответствующей размерности. Тогда можно описать такую процедуру:

Procedure KolOtr1(X : MyArray2; n, m : integer; Var Y : MyArray1);
Var
  i, j : integer;
Begin
  for i := 1 to n do
    begin
      Y[i] := 0; {записываем начальное значение количества элементов в соответствующую столбцу ячейку}
      for j := 1 to m do
        if X[i, j] < 0 {если отрицательный элемент найден}
          then
            Inc(Y[i]); {то увеличиваем текущее значение на единицу}
    end;
End;

Способ 2 - использовать счетчик, находить количество элементов строки и выводить значение на экран.

Procedure KolOtr2(X : MyArray2; n, m : integer);
Var
  i, j, k : integer;
Begin
  for i := 1 to n do
    begin
      k := 0;
      for j := 1 to m do
        if X[i, j] < 0
          then
            Inc(k);
      writeln(i,' - ', k);
    end;
End;

Вопрос. Сравните предложенные способы решения задачи. Какой способ Вам понравился больше и почему?

Определить, отвечает ли заданный массив некоторым требованиям

Задача. Определить, есть ли в заданном массиве элемент, равный 0.

Опишем логическую функцию, значение которой равно истине, если такой элемент есть, и ложно в противном случае. Самый простой способ - это просматривать элементы и, если найден искомый элемент, то присвоить функции значение True, иначе - False.

Function Check1(X : MyArray2; n, m : integer) : Boolean;
Var
  i, j : integer;
  Flag : Boolean;
Begin
  Flag := False; {Предполагаем, что искомого элемента в массиве нет}
  i := 1;
  while not(Flag) and (i<=n) do {элемент не найден и строки не закончились}
    begin
      j := 1;
      while (j<=m) and (X[i, j]<>0) do {перебираем все элементы текущей строки, пропуская ненулевые элементы}
        Inc(j);
      Flag := not(j=m+1);{если искомый элемент найден, то переменной Flag присваиваем значение True}
      Inc(i);
    end;
  Check1 := Flag;
End;

Задача. Определить, является ли данный квадратный массив симметричным относительно своей главной диагонали.

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

Заметим, что если массив является симметричным, то для него выполняется равенство A[i, j]=A[j, i] для всех i=1, ..., n и j=1, ..., n. Поэтому можно составить следующую функцию:

Function Check2(X : MyArray; n : integer) : Boolean;
Var
  i, j : integer;
  Flag : Boolean;
Begin
  Flag := True; {Предполагаем, что матрица симметрична}
  i := 2;
  while Flag and (i<n) do
    begin
      j := 1;
      while (j<i) and (X[i, j]=X[j, i]) do
        Inc(j);
      Flag := (j=i);
      Inc(i);
    end;
  Check2 := Flag;
End;

 Вопрос. Почему в функции употребляется условие i>j? Можно ли без него обойтись и что при этом изменится?

Изменение значений некоторых элементов, удовлетворяющих заданному свойству

Задача. В массиве размерностью NxM к элементам четных столбцов прибавить элемент первого столбца соответствующей строки.

Procedure Izmenenie1(Var X : MyArray2; n, m : integer);
Var
  i, j : integer;
Begin
  for i := 1 to n do
    for j := 1 to m div 2 do
      Inc(X[i, 2*j], X[i, 1]);
End;

Вопрос. Какой смысл вложен в оператор цикла for j := 1 to m div 2 do?

Задача. Заменить все отрицательные элементы на противоположные.

Procedure Izmenenie2(Var X : MyArray2; n, m : integer);
Var
  i, j : integer;
Begin
  for i := 1 to n do
    for j := 1 to m do
      X[i, j] := Abs(X[i, j]);
End;

Заполнение массива по правилу

Задача. Заполнить массив А размером NxM "змейкой" следующим образом:
  1   2   3   4   5   6   7
14 13 12 11 10   9   8
15 16 17 18 19 20 21
28 27 26 25 24 23 22

Для того, чтобы заполнить, надо определить правило заполнения, а оно в данном случае будет таким:
если ряд нечетный, то A[i, j]=(i-1)*m+j;
если ряд четный, то A[i, j]=i*m-j+1.

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

Procedure FillArray(Var X : MyArray2; n, m : integer);
Var
  i, j : integer;
Begin
  for i := 1 to n do
    for j := 1 to m do
      if i mod 2 =1
        then
          X[i, j] := (i-1)*m+j
        else
          X[i, j] := i*m-j+1;
End;

Задание. Вставьте в программу-шаблон рассмотренные подпрограммы и организуйте выбор одной из них через меню. Дополните подпрограммы, не содержащие пояснений, соответствующими комментариями. Сохраните файл на дискете.