
Общие сведения
Двумерные массивы имеют аналогию с таким понятием в математике, как матрица. Двумерный массив - это массив, элементами которого являются одномерные массивы:
int b [N] [M];
float а [10] [5];
В описании N - количество строк, М - количество столбцов матрицы.
При изменении второго индекса на единицу перемещение идет вдоль строки, а при изменении первого индекса на единицу - вертикально вдоль столбца. Обычно в качестве идентификатора номера строки используют символ i, а столбца – j. Тогда к элементу массива, описанному выше, можно обратиться по имени b [i] [j].
Ниже приведены примеры описания двумерных массивов и обращения к элементам:
а[i] [j] = 13.13;
а[0][1] = 8;
b[5,6]:=7;
b[i,8]:=0;
При обработке двумерных массивов возникают такие задачи, как и при обработке одномерных массивов: ввод элементов массива, нахождение суммы, произведения, среднего и т. д., поиск некоторого элемента в массиве, сортировка элементов массива, вывод элементов массива.
На рис. 20 приведена схема алгоритма формирования элементов массива с помощью датчика случайных чисел, вывод элементов массива на экран, вычисление суммы всех элементов двумерного массива. Программа дана в примере рr22.
// Пример pr22
#include <stdio.h>
#
71
void main()
{
const int N1=10, // Максимальное число строк матрицы
M1=10; // Максимальное число столбцов матрицы
int a[N1][M1], // Матрица
i, // Текущий номер строки
j, // Текущий номер столбца n,m,s; // Текущий размер матрицы
printf(Введите число строк и столбцов массива: ");
scanf("%d%d",&n,&m"); randomize(); for (i=0; i<n; i++)
for (j=0; j<m; j++)
a[i][j] = random(10);
printf("Полученный массив \n");
for (i=0; i<n; i++)
{
for (j=0; j<n; j+)
printf("%5d",a[i][j]);
printf("\n");
}
s=0;
for (i=0; i<n; i++)
for (j=0; j<m; j+)
s=s+a[i][j]; printf("s=%d\n",s); getch();
}
Анализируя предложенную программу, можно заметить, что для ввода, вывода и нахождения суммы элементов массива используются три раза вложенные циклы. Так как массив располагается в непрерывной области памяти построчно, более рационально будет и обрабатывать элементы построчно. В программе во вложенных циклах для каждого значения индекса i индекс j изменяется от 0 до m - 1, т. е. индекс j изменяется чаще. Таким образом обрабатываются элементы массива построчно. При выводе элементов массива на экран для каждого значения i в теле цикла выполняются два оператора: первый оператор цикла выводит на экран в строчку элементы одной строки, а второй оператор вывода переводит курсор на новую строку, что как раз и обеспечивает вывод матрицы в виде прямоугольника.
72
73
Следующий пример иллюстрирует работу с диагоналями матрицы. Дана квадратная матрица. Требуется отрицательные элементы побочной диагонали заменить суммой элементов главной диагонали матрицы. При изучении поставленной задачи следует напомнить, что главная диагональ проходит из правого верхнего в левый нижний угол. Так как мы работаем с квадратной матрицей, только на главной диагонали будут лежать элементы, индексы строк и столбцов которых одинаковы. Именно этот факт и используется при решении задачи. Мы не будем перебирать все элементы массива и проверять, совпали ли индексы, а сразу задаем оба индекса с помощью одного идентификатора i. Побочная диагональ проходит из правого верхнего в левый нижний угол матрицы. Нетрудно заметить, что при движении по побочной диагонали номер строки возрастает от 1 до n, номер столбца убывает от n до 1. Значит, только на побочной диагонали лежат элементы, у которых номер столбца определяется по формуле j = n-i+1. В то же время, если обратить внимание на эту формулу в программе, она там другая j=n-i-1, так как индексы в языке C++ изменяются от 0. Программа приведена в примере рr23, графическая схема алгоритма на рис. 21.
// Пример рr23
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
void main()
{
const int N1=10, // максимальное число строк матрицы
M1=10; // максимальное число столбцов матрицы
int a[N1][M1], // матрица
i, // текущий номер строки
j, // текущий номер столбца
n,m,s; // текущий размер матрицы
printf("Введите число строк и столбцов массива:");
scanf("%d%d",&n,&m"); printf("Введите элементы матрицы \n");
for (i=0; i<n; i++)
for (j=0; j<m; j++)
scanf("%d",&a[i][j]);
printf("Исходный массив \n");
for (i=0; i<n; i++)
{ for (j=0; j<m; j++)
printf("%5d",a[i][j]);
printf("\n");
74
Рис. 21
75
s=0;
for (i=0; i<n; i++) / /Сумма элементов главной диагонали
s=s+a[i][j]; printf("s=%d\n",s); for (i=0; i<n; i++) // Замена элементов побочной диагонали
{
j=n-i-1;
if (a[i][j]<0) a[i][j]=s;
}
printf("Полученный массив\n ");
for (i=0; i<n; i++)
{
for (j=0; j<m; j++)
printf("%5d",a[i][j]);
printf("\n");
}
getch();
}
Рассмотрим пример обработки двумерных массивов: в прямоугольной матрице отсортировать столбцы в порядке убывания максимальных элементов столбцов.
Решение задачи сводится к формированию одномерного массива из максимальных элементов столбцов, затем сортируется этот одномерный массив и параллельно - столбцы матрицы. Чтобы не запутаться в этой задаче, используем знакомый метод сортировки "пузырьком". Исходный массив имеет идентификатор а, промежуточный одномерный массив - b. Графическая схема алгоритма приведена на рис. 22, программа - в примере рr24.
// Пример pr24 #include <stdio.h>
#include <conio.h>
void main()
{
const int N1=10, // максимальное число строк матрицы
M1=10; // максимальное число столбцов матрицы
int a[N1][M1], // матрица
b[M1], // Вспомогательный одномерный массив из
// максимальных элементов столбцов
i, // текущий номер строки
j, // текущий номер столбца
n,m // Текущий размер матрицы
d,fl; // Дополнительная переменная и флаг перестановок
printf ("Введите число строк и столбцов массива:");
76
printf("Bведите элементы матрицы \n");
for (i=0; i<n; i++)
for (j=0, j<m; j++)
scanf("%d",&a[i][j]);
printf("Исходный массив \n ");
for (i=0; i<n; i++)
{
for (j=0, j<m; j++)
printf("%5d",a[i][j]);
printf("\n");
}
// Формирование одномерного массива из максимальных
// элементов столбцов
for (j=0, j<m; j++) // Перебираем все столбцы
{
b[j]=а[0][j]; // Пусть первый элемент в столбце максимальный
for (i=1; i<n; i++) // Перебираем все элементы в столбце
if (a[i][j]>b[j]) b[j]=a[i][j];
}
// Сортировка одномерного и двумерного массива
do
{
fl=1; // Поднять флаг
for (j=0, j<m-1; j++) // Перебираем элементы
// одномерного массива
if (b[j]>b[j+1]) // Проверить, нужна ли перестановка
{
fl=0; // Опустить флаг
// Переставить элементы одномерного массива и
d=b[j];
b[j]=b[j+1];
b[j+1]=d;
// столбцы двумерного массива
for (i=0; i<n; i++)
{
d=a[i][j];
a[i][j]=a[i][j+1];
a[i][j+1]=d;
}
}
77
78
while(!fl); // Завершить сортировку, если флаг не опускается
printf("Отсортированный массив \n");
for (i=0; i<n; i++)
{
for (j=0, j<m-1; j++)
printf("%5d",a[i][j]);
printf("\n");
}
getch();
}
В этой программе можно обойтись без дополнительного массива, но тогда пришлось бы во время сортировки массива каждый раз находить максимальный элемент столбца, даже если максимальный в этом столбце мы уже находили.
Контрольные вопросы
1. Чем матрица отличается от одномерного массива?
2. Как изменяются индексы элементов матрицы, лежащих выше главной диагонали?
3. Как изменяются индексы элементов матрицы, лежащих ниже главной диагонали?
4. Как изменяются индексы элементов матрицы, лежащих выше побочной диагонали?
5. Как изменяются индексы элементов матрицы, лежащих ниже побочной диагонали?
6. В чем принципиальное отличие двух следующих фрагментов программ:
a) for (i=1; i<n; i++)
for (j=0; j<m; j++)
s=s+a[i][j]; б) for (j=1; j<m; j++)
for (i=0; i<n; i++)
s=s+a[i][j];
Варианты заданий
1. Получить матрицу B[N][M] из матрицы A[N][M] путем перестановки столбцов - первого с последним, второго с предпоследним и т. д.
2. В произвольной матрице A[N][M] поменять местами в каждой строке минимальный и максимальный элементы.
3
79
4. В квадратной матрице A[N][N] найти среди элементов, расположенных ниже диагонали, минимальный элемент, а среди элементов выше побочной диагонали - максимальный. Поменять их местами. Вывести координаты этих элементов.
5. В квадратной матрице A[N][N] определить среди элементов, расположенных ниже побочной диагонали, количество положительных элементов, а среди элементов выше главной диагонали - количество отрицательных элементов.
6. Дана целочисленная матрица A[N][N]. Сформировать одномерный массив X[2N] по следующему правилу: элементами одномерного массива с нечетными индексами будут элементы главной диагонали матрицы, а с четными - побочной диагонали. Определить, какое значение массива X чаще всего встречается в нем самом.
7. Сформировать одномерный массив X[N] из сумм положительных элементов строк матрицы, попутно определяя номера строк матрицы, в которых отсутствуют положительные элементы.
8. Сформировать одномерный массив В[М] из максимальных элементов столбцов прямоугольной матрицы A[N][M]. В массиве В поменять местами первый отрицательный и последний положительный элементы.
9. В квадратной матрице A[N][N] заменить элементы главной и побочной диагоналей на минимальный элемент, найденный среди элементов, расположенных ниже главной диагонали.
10. В произвольной матрице А[М][М] поменять местами строку, содержащую минимальный элемент матрицы, со строкой, содержащей максимальный элемент.
11. В квадратной матрице A[N][N] поменять местами максимальный элемент главной и побочной диагоналей с элементом, стоящим на пересечении этих диагоналей.
12. В квадратной матрице A[N][N] определить номер столбца матрицы, имеющего наибольшую сумму элементов. Поменять этот столбец со строкой, имеющей наименьшую сумму элементов.
13. Дана матрица A[N,N]. Сформировать одномерный массив X из полусумм элементов главной и побочной диагоналей в соответствующей строке матрицы. Упорядочить элементы одномерного массива в порядке убывания.
14. Дана матрица A[N,N]. Определить, является ли заданная матрица симметричной (относительно главной диагонали).
15. Дана матрица A[N,M]. Определить количество "особых" элементов матрицы, считая элемент "особым", если он больше суммы, остальных элементов своего столбца.
1
80
17. Дана матрица A[N,M]. Определить количество элементов матрицы, являющихся простыми числами.
18. Дана матрица A[N,M]. Упорядочить элементы каждой строки в порядке убывания.
19. Дана матрица A[N,M]. Упорядочить строки матрицы в порядке убывания их первых элементов.
20. Дана матрица A[N,M]. Определить, в какой строке матрицы находится наибольшее количество нулей.
21. В матрице A[N,N] найти наибольшее из значений элементов, расположенных в заштрихованной части матрицы (рис. 23).
Рис. 23
22. Дана матрица A[N,M]. Заменить элементы матрицы, являющиеся простыми числами, нулем.
23. Дана матрица A[N,N]. Транспонировать матрицу.
24. Дана матрица A[N,N]. Получить новую матрицу из матрицы A[N,N] путем перестановки сегментов в соответствии с рис.24.
25. Дана матрица A[N,N]. Заменить строку, имеющую наименьшую сумму, на элементы главней диагонали.
81
ЛАБОРАТОРНАЯ РАБОТА №6
ДИНАМИЧЕСКИЕ МАССИВЫ
Цель работы:
Приобретение навыков использования динамической памяти, обработки двумерных массивов, составления алгоритмов и программ, использующих сложные циклы.
Порядок выполнения работы:
В соответствии с поставленной задачей необходимо разработать графическую схему алгоритма, составить два варианта программы, в которой под массивы выделяется динамическая память (в первом варианте элементы массива перебирать с помощью указателей, а во втором – с индексов) и отладить ее в среде С++, продемонстрировать преподавателю, подготовить отчет, и ответить на контрольные вопросы и защитить лабораторную работу перед преподавателем.