Вы на НеОфициальном сайте факультета ЭиП

На нашем портале ежедневно выкладываются материалы способные помочь студентам. Курсовые, шпаргалки, ответы и еще куча всего что может понадобиться в учебе!
Главная Контакты Карта сайта
 
Где мы?
» » » Работа с двумерными массивами в С++

Реклама


Работа с двумерными массивами в С++

Просмотров: 6566 Автор: admin

Синтаксис Си разрешает использовать только одномерные массивы. Массивы большей размерности трактуются как массивы массивов. Использование статических многомерных массивов имеет некоторые особенности, которые можно рассмотреть на примере двумерных массивов (матриц).

Объявление двумерного массива требует, чтобы были указаны два размера: число строк и число столбцов матрицы, например:

int   a [8][10];                       // Массив из 8-ми одномерных массивов,

// в каждом из которых 10 элементов.

float          b [5] [5] [5];                            // Массив из пяти матриц, каждая

                                             // из которых имеет 5 строк по 5 элементов.

При объявлении массива таким образом, в памяти выделяется место под размещение его элементов. Элементы двумерного массива размещаются линейно по возрастанию индексов (построчно). Индексы нумеруются с нуля.

Инициализация двумерных массивов синтаксически выглядит как инициализация нескольких одномерных массивов, например:

int   a [3] [4] =   {

{1, 2, 3, 4},        // Значения элементов нулевой строки.

                                    {2, 4, 6, 8},          // Значения элементов первой строки.

                                    {9, 8, 7, 6}// Значения элементов второй строки.

                                    };

При размещении в памяти будет выделено место под запись 3 * 4 = 12 элементов, и они будут размещены линейно в следующем порядке:

1

2

3

4

2

4

6

8

9

8

7

6

Нулевая строка

Первая строка

Вторая строка

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

Пусть матрица имеет размер, определенный в описании. Пусть реальный размер обозначен переменными n, m (матрица имеет n строк и m столбцов, при этом нумерация начинается с нулевого значения). Пусть i – номер строки, j – номер элемента в столбце (текущие значения). Обращение к элементу массива aij можно выполнить по индексу (прямая адресация) или указателю (косвенная адресация):

a [i][j]                          // Адресуется элемент массива, стоящий на

// пересечении i-того столбца и j-той строки.

* (a+i * m + j)             // Адресуется элемент массива, отстоящий от его

// адреса на i * m + j значений.

При косвенной адресации важно, что константа m (количество элементов в строке) определяет разбиение адресного пространства, выделенного для матрицы, на строки определенной длины.

Способы адресации элементов матрицы рассмотрим на примере. При решении любой задачи, в которой требуется обращение ко всем элементам матрицы, алгоритм просмотра содержит вложенный цикл, у которого во внешнем цикле управляющей переменной служит номер строки матрицы, а во внутреннем – номер столбца. Тогда просмотр элементов происходит построчно.

Пусть есть описание матрицы:


#define                      n         5
#define                      m        7

int       a[n][m];
Здесь размер матрицы определяют define – константы. Для матрицы условно переменной длины следует описать размер по максимуму, и ввести переменные, реально определяющие размер матрицы.
int       a[25][25];                    // Максимальное число строк, столбцов.
int       n, m;                            // Реальное число строк, столбцов.
           …
printf ("Введите размер матрицы (строк, столбцов <25)n");
scanf ("%d%d", &n, &m);    // Теперь это наибольшие значения параметров цикла.
Для обращения к элементам матрицы по строкам цикл записывается так:
           for (i = 0; i<n; i ++)
                       for(j = 0; j<m; j ++)
                                  {
                                             // В теле цикла обращение к переменной a[i][j].
                                  }
Если переменить эти циклы местами, просмотр будет происходить по столбцам:
           for( j = 0; j<m; j ++)
                      for (i = 0; i<n; i ++)
                                  {
                                             // В теле цикла обращение к переменной a[i][j].
                                  }
Зная, что матрица хранится как одномерный массив, можно ее описать как одномерный массив, а элементы адресовать как элементы матрицы, например:
int       a[25];                         // Матрица 5 на 5.
           
int       n, m;
           n = 5;
           m = 5;
Независимо от способа описания двумерного массива, обращение к его элементам с использованием указателя, выполнит те же действия, что и обращение по индексам, а синтаксически должно быть записано так:
for (i = 0; i<n; i ++)
           for(j = 0; j<m; j ++)
                       {
                                  // В теле цикла обращение к переменной * (a+i * m + j)
                       }

Как видим, запись сложного цикла нисколько не изменилась, а изменился только синтаксис обращения к переменной.

Использование функций при обработке матриц предполагает два кардинально различных подхода. В первом случае матрица существует или рассматривается как самостоятельная структура данных, к которой необходимо применить какой-либо алгоритм обработки. В качестве параметра такой функции будет использована вся матрица целиком. Чтобы задача обработки решалась бы в общем виде, в функцию следует передать имя матрицы и ее размеры (как параметры функции), при этом функция получает матрицу как двумерный массив. Си++ должен знать, каков способ разбиения этой структуры на строки, поэтому число строк данных как константное выражение можно опустить, а число данных в каждой строке опускать нельзя. Оно должно быть указано обязательно как константное выражение в квадратных скобках при передаче матрицы. Так, прототип функции, получающей матрицу в качестве входного данного, может выглядеть так:

int function (int a [][m], int n, int m);        // Здесь m – константноевыражение.

Пример №1. В качестве простого примера рассмотрим функции для ввода и вывода матрицы на экран. Предполагается, что матрица условно переменного размера, поэтому число строк и столбцов матрицы по описанию определено define – константами N = 5 и M = 5. Реальный размер матрицы определяют переменные n, m, значения которых вводятся.


#include         <stdio.h>
#define                      N         5
#define                      M        5
voidinput_matr (inta[][M], int &n, int &m);    // Важно, что длина строки, это константа.
voidprint_matr (inta[][M], intn, intm);        // Число строк можно не передавать.
// Главная программа описывает входные данные.
void main(void)
{
int       n, m;                                     // Реальные размеры матрицы.
int       matr [N][M];                         // Описан двумерный массив.
input_matr (matr, n, m);                  // Передан в функцию ввода.
print_matr (matr, n, m);                  // Предан в функцию вывода.
}
// Описание функции ввода. Параметры функции – имя и размеры массива.
void input_matr (int a[][M], int &n, int &m)               // n, m возвращаютсяпоссылке.
{
int       i, j;
printf ("Введите размер матрицы не более %d на %dn", N, M);
scanf ("%d%d", &n, &m);
printf ("Введите матрицу.n");
           for (i = 0;i < n; i ++)
                       for (j = 0; j < m; j ++)
                                  scanf("%d", &matr[j]);
}
// Описание функции вывода. Параметры функции – имя и размеры массива.
void print_matr (int a[][M], int n, int m)
{
int       i, j;
           for (i = 0; i < n; i ++)
                       {
                                  for (j = 0; j<m; j++)
                                             printf ("%5d", mas[j]);
                                  printf ("n");                      // Разбиение вывода на строки.
                       }
}

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

Пример №2. При решении задач на обработку одномерных массивов, нами были отлажены функции обработки одномерных массивов. Их смело можно применить для решения задач обработки многомерных массивов. Пусть есть функции вывода одномерного массива, и функция преобразования, которая находит наименьшее значение и переставляет его на первое место. Для ввода матрицы используем функцию ввода из примера №1.


#include <stdio.h>
#define           N         5
#define           M        5
// Есть функция вывода одномерного массива.
void print_mas(int mas[], int len)             // Вывод массива в общем виде
{
           for (int i = 0; i < len; i ++)
                       printf("%5d", mas);
           printf("n");
}
// На ее основе можно легко описать функцию вывода матрицы как совокупности
// одномерныхмассивов.
void print_matr (int mas[][M], int n, int m)
{
printf  ("Матрица:n");
           for (int i = 0; i < n; i ++)
                       print_mas(mas[i],m);          // Обращение к функции вывода массива.
}
// Есть функция преобразования одномерного массива в соответствии с условием.
void Change (int mas[], int len)
{
// Найдем наименьший элемент.
int       *ip;
int       *min = mas;
           for (ip = mas; ip < mas+len; ip ++)
                       if (*ip < *min) 
                                  min = ip;
// Перестановка при завершении поиска.
           *ip = *min;
           *min =*mas;
           *mas = *ip;
}
// main должна объявить матрицу и выполнить управление вызовами функций.
void main(void)
{
int       n, m;
int       matr [N][M];                                  // Матрица объявлена размером 5 на 5.
int       i;
           input_matr (matr, n, m);                // Передан в функцию ввода.
// Для преобразования матрицы ее строки передаются в функцию по очереди как
// одномерные массивы. Цикл управления находится в основной программе.
// и управляет передачей строк в функцию.
           for (i = 0;i < n;i ++)
                       Change (matr, m);           // matr, это i – таястрокаматрицы.
// Функция вывода матрицы вызывается после завершения обработки.
           print_matr (matr, n, m);
}
Пример №3. Просмотр матрицы по столбцам вызовет существенные изменения в основной программе, потому что столбец нельзя передать как одномерный массив простой записью matr [j] в силу того, что двумерный массив, это массив массивов (строк для матрицы). Однако функции обработки одномерных массивов можно применить для решения задач обработки столбцов, если предварительно столбец копировать в некую промежуточную структуру, а после преобразования возвращать измененное значение столбцу матрицы. Так, основной цикл главной программы примера №2 будет выглядеть так:
int       Tmp[M];                     // Временный массив, его длина равна длине столбца.
for (j = 0;j < m;j ++)              // Цикл по номерам столбцов.
           {
           // Копирование перед каждым обращением.
                       for (i = 0;i < n; i++)                      // Цикл по номеру элемента в строке.
                                  Tmp  = matr [j];                  // Tmp получил копию j-того столбца.
                       Change(Tmp,m);                          // Изменение в Tmp.
           // Копирование после каждого обращения.
                       for (i = 0;i < n; i++)
                                  matr [i][j] = Tmp [i];                  // Возвращаем значение j-тому столбцу.
           }
// Выводобычный.
           print_matr(matr,n,m);
           
Пример №4. Чтобы убедиться в преимуществах косвенной адресации покажем, как можно работать с одномерным массивом как с матрицей. Найдем сумму элементов матрицы.
#include <stdio.h>
// Функция ввода матрицы получает одномерный массив.
// Он разбит на n строк по m элементов в каждой.
// Косвенная адресация позволяет рассматривать двумерный массив как линейный.
// Функция ввода матрицы.
void input_matr (int mas [], int &n, int &m)
{
int       i, j;
           printf ("Введи размер матрицыn");
           scanf ("%d%d", &n, &m);
           printf("Введи матрицуn");
           for (i = 0; i < n; i ++)
                       for( j = 0; j < m; j ++)
                                  scanf ("%d", mas + i*m + j);
}
// Функция вывода матрицы.
void print_matr (int mas[], int n, int m)
{
int       i, j;
           for (i = 0; i < n; i ++)
           {
                       for (j = 0; j < m; j ++)
                                  printf("%5d", *(mas+i*m+j));
                       printf("n");
           }
}
// Функция нахождения суммы элементов матрицы.
int Sum (int mas[], int n, int m)
{
int       i, j;
int       S = 0;
           for (i = 0; i < n; i ++)
                       for(j = 0; j < m; j ++)
                                  S+=*(mas+i*m+j);
           return S;
}
// В главной программе объявлен одномерный массив. Он передается во все функции.
void main(void)
{
int       matr[25];
int       n, m;
           input_matr (matr, n, m);
           printf ("Сумма элементов равна %dn", Sum (matr,n,m) );
           print_matr (matr, n, m);
}

Варианты заданий

Задание 1. Дана матрица размером n*m. Найти суммы элементов в каждой строке матрицы, для чего использовать функцию, находящую сумму элементов одномерного массива. Дополнить матрицу найденными значениями, поместив их в конце каждой строки.

Задание 2. Дана матрица размером n*m. Упорядочить матрицу по возрастанию элементов первого столбца. Использовать метод пузырька. Алгоритм заключается в следующем: матрица просматривается по перекрещивающимся парам чисел (а[0], a[i+1][0]). Если нулевой элемент i-той строки больше, чем нулевой элемент i+1-ой строки, то строки меняются местами. Поскольку строки матрицы, это одномерные массивы, имеет смысл написать функцию перемены указателей, адресующих строки а и а[i+1]. Перестановки подсчитываются. Алгоритм завершает работу, если при просмотре матрицы нет ни одной перестановки.

Задание 3. Дана матрица размером n*m. Найти и заменить нулем максимальное и минимальное значения в каждой строке матрицы. Использовать функцию, находящую минимум, и функцию, находящую максимум из элементов одномерного массива. Передавать им по очереди строки матрицы.

Задание 4. Дана матрица размером n*m. Определить, является ли она симметричной относительно главной диагонали. Использовать логическую функцию.

Задание 5. Дана матрица размером n*3. Она содержит результаты измерений прямых круговых конусов: радиус основания, высота, длина образующей. Найти и сохранить в этой же матрице значения объема и площади поверхности каждого конуса. Использовать функции. Найти конус наибольшей площади и наибольшего объема, для чего использовать функцию поиска максимума в одномерном массиве.

Задание 6 .Дана матрица размером n*m. Выполнить сглаживание в строках матрицы, которое заключается в замене каждого элемента значением среднего арифметического трех стоящих рядом значений. Использовать функцию, выполняющую сглаживание в одномерном массиве. Передавать ей по очереди строки матрицы.

Задание 7. Дана матрица размером n*m. Преобразовать матрицу, удалив из нее i-тую строку и (или) j-тый столбец (по желанию пользователя). Использовать функцию преобразования матрицы.

Задание 8. На плоскости заданы n точек своими координатами. Построить матрицу расстояний между всеми точками. Найти наибольшее расстояние. Найти, между какими точками расстояние наибольшее. Использовать функции для вычисления расстояния между двумя точками и для поиска наибольшего значения.

Задание 9. Дана матрица размером n*m. Определить, являются ли упорядоченными по возрастанию данные в каждой строке матрицы. Напечатать исходную матрицу по строкам, в конце каждой строки напечатать сообщение о том, упорядочена строка или нет. Использовать функцию, выполняющую проверку в одномерном массиве. Передавать ей по очереди строки матрицы. Использовать функцию печати строки сообщения.

Задание 10. Заданы несколько матриц произвольного размера. Описать функцию сложения (вычитания) матриц. Передавать как один из параметров функции знак действия («+» или «–»). Чтобы контролировать входные данные, функция должна быть логической.

Задание 11. Дана матрица размером n*m. Преобразовать матрицу следующим образом: найти в каждой строке минимальный и максимальный элементы и поменять их местами с первым и последним элементами строки. Использовать функции, выполняющие поиск минимума и максимума в одномерном массиве. Использовать функцию для выполнения перестановки. Передавать им по очереди строки матрицы.

Задание 12. Получить трехдиагональную матрицу размером n*n, у которой на главной диагонали и двух, лежащих выше и ниже ее расположены единицы, а остальные элементы равны нулю.

Задание 13. Дана матрица размером n*m. Заменить нулями элементы i-той строки и (или) j-того столбца (по желанию пользователя). Использовать функцию преобразования матрицы.

Задание 14. Дана матрица размером n*m. Определить, являются ли упорядоченными по возрастанию данные в каждом столбце. Напечатать исходную матрицу по строкам, внизу каждого столбца напечатать сообщение о том, упорядочен столбец, или нет. Использовать функцию, которая решает задачу для элементов одномерного массива. Передавать ей по очереди столбцы матрицы.

Задание 15. Исходные данные, это два массива коэффициентов: A и B. Вычислить матрицу решений всех линейных уравнений вида Ai*x + Bj = 0. Использовать функцию.

Задание 16. Дана матрица размером n*m. Выполнить выравнивание в матрице, заменяя те значения, которые по абсолютной величине больше некоторого M (введенного в диалоге), значением M с учетом знака. Использовать функцию преобразования одномерного массива или матрицы.

Задание 17. Дана матрица размером n*m. Найти и заменить нулем максимальное и минимальное значения в каждом столбце матрицы. Использовать функции, выполняющие поиск минимума и максимума в одномерном массиве. Передавать им по очереди столбцы матрицы.

Задание 18. Дана матрица размером n*m. Найти норму матрицы: максимальное значение из сумм элементов в каждой строке. Использовать функцию суммирования с сохранением всех найденных сумм. Использовать функцию поиска максимума в одномерном массиве.

Задание 19. Дана матрица размером n*m. Найти суммы элементов в каждом столбце матрицы и дополнить матрицу найденными значениями, поместив их в конце каждого столбца. Использовать функцию, находящую сумму элементов одномерного массива. Передавать ей по очереди столбцы матрицы.

Задание 20. На плоскости заданы n точек своими координатами. Построить матрицу расстояний между всеми точками. Найти равноудаленные точки, если такие есть, и сохранить в отдельном массиве их номера. Использовать функции построения и поиска.


Информация

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

Популярные новости

Статистика сайта



Rambler's Top100



 
Copyright © НеОфициальный сайт факультета ЭиП