Поможем написать учебную работу
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.

Предоплата всего

Подписываем
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Предоплата всего
Подписываем
Лабораторная работа № 8
Цель работы - изучить операторы, используемые при организации вычислительных процессов обработки двумерных массивов данных, получить практические навыки в составлении подобных программ.
2 Общие сведения
2.1 Прямоугольные массивы
Прямоугольный массив имеет более одного измерения. Многомерным называется такой массив, который характеризуется двумя или более измерениями, а доступ к отдельному элементу осуществляется посредством двух или более индексов.
Чаще всего в программах используются простейшие многомерные массивы - двумерные массивы. В двумерном массиве позиция любого элемента определяется двумя индексами. Если представить двумерный массив в виде таблицы данных, то один индекс означает строку, а второй - столбец. Чтобы объявить двумерный массив целочисленных значений размером A x B, достаточно записать следующее:
int[,]имя_массива = new int[A,B];
Чтобы получить доступ к элементу двумерного массива, необходимо указать оба индекса, разделив их запятой. Например, чтобы присвоить число Z элементу двумерного массива, позиция которого определяется координатами x и y, можно использовать следующую инструкцию:
имя_массива[x,y] = Z;
Многомерный массив можно инициализировать, заключив список инициализаторов каждой размерности в собственный набор фигурных скобок. Например, вот каков формат инициализации многомерного массива:
тип[,] имя_массива = {
{val, val, val, …, val}
{val, val val, …, val}
…
{val, val, val, …, val}
};
Здесь элемент val значение инициализации. Каждый внутренний блок означает
строку. В каждой строке первое значение будет сохранено в первой позиции массива, второе значение - во второй и т.д.
Варианты описания двумерного массива:
тип[,] имя;
тип[.] имя = new тип [ разм_1, разм_2 ];
тип[.] имя = { список_инициализаторов };
тип[,] имя = new тип [,] { список_инициализаторов };
тип[,] имя = new тип [ разм_1, разм_2 ] { список_инициализаторов };
Примеры описаний (один пример для каждого варианта описания):
int[ , ] а; / / 1 элементов нет
int[ , ] b = new int [2, 3]; / / 2 элементы равны 0
int[ , ] с = {{1, 2, 3}, {4, 5, 6}}; / / 3 new подразумевается
int[ , ] c = new int[ , ]] {{1. 2. 3). {4, 5. 6}}: / / 4 размерность вычисляется
int[ , ] d = new int[2,3 ]] {{1. 2. 3). {4, 5. 6}} / / 5 избыточное описание
Если список инициализации не задан, размерности могут быть не только константами, но и выражениями типа, приводимого к целому. К элементу двумерного массива обращаются, указывая номера строки и столбца, на пересечении которых он расположен, например:
а[1,4] b[i, j] b[j, i]
Необходимо помнить, что компилятор воспринимает как номер строки первый индекс, как бы он ни был обозначен в программе.
Пример 1. Для целочисленной матрицы размером m*n вычислить сумму элементов в каждой строке (рис. 1).
Рисунок 1 - Матрица из m строк и n столбцов
Нахождение суммы элементов каждой строки требует просмотра матрицы по строкам. Схема алгоритма приведена на рис. 2, программа в листинге 1.
Рисунок 2- Схема алгоритма к примеру 1
Листинг 1- Программа к примеру 1
using System;
namespace ConsoleApplication1
{
class Class1
{
static void Main()
{ const int m = 3, n = 4;
int[,] a = new int[m, n] {
{ 2, 2, 8, 9 },
{ 4, 5, 6, 2 },
{ 7, 0, 1, 1 }
};
Console.WriteLine("Исходный массив:");
for ( int i = 0; i < m; ++i)
{
for ( int j = 0; j < n; ++j )
Console.Write( " " + a[i, j]);
Console.WriteLine();
}
for ( int i = 0; i < m; ++i )
{
int sum = 0;
for ( int j = 0; j < n; ++j )
sum += a[i, j];
Console.WriteLine("В строке {0}сумма элементов {1}",i, sum );
}
Console.Read();
}
}
}
Результаты работы программы:
Следует обратить внимание на то, что переменная sum обнуляется перед циклом просмотра очередной строки матрицы, поскольку для каждой строки его вычисление начинается заново.
2.2 Ступенчатые массивы
В ступенчатых массивах количество элементов в разных строках может различаться. В памяти ступенчатый массив хранится иначе, чем прямоугольный: в виде нескольких внутренних массивов, каждый из которых имеет свой размер. Кроме того, выделяется отдельная область памяти для хранения ссылок на каждый из внутренних массивов. Организацию ступенчатого массива иллюстрирует рис. 3.
Рисунок 3 - Ступенчатый массив
Описание ступенчатого массива:
тип[ ] [ ] имя;
Под каждый из массивов, составляющих ступенчатый массив, память требуется выделять явным образом, например:
int[ ] [ ] а = new int [3][ ]; / / выделение памяти под ссылки на три строки
а[0]= new int [5]; / / выделение памяти под 0-ю строку (5 элементов)
а[1] =new int [3]; / / выделение памяти под 1-ю строку (3 элемента)
а[2] = new int [4]; / / выделение памяти под 2-ю строку (4 элемента)
Здесь а[0], а[1] и а[2] это отдельные массивы, к которым можно обращаться по имени ниже (листинг 3) приведен пример работы со ступенчатым массивом с использованием выделения памяти под каждую строку.
Другой способ выделения памяти:
int[ ] [ ] а = { new int[5], new int[3], new int[4] };
K элементу ступенчатого массива обращаются, указывая каждую размерность в своих квадратных скобках, например:
a[1][2] a[i][j] a[j][i]
В остальном использование ступенчатых массивов не отличается от использования прямоугольных.
Пример 2. Поиск максимального элемента в двумерном массиве.
Решение поставленной задачи осуществляется с помощью цикла по параметру i, изменяющегося шагом +1 от 0 до m-1 с вложенным циклом по параметру j, изменяющемуся шагом +1 от 0 до n-1.
Перед входом в цикл переменной max присваивается значение у[0,0] элемента массива. С каждым изменением параметра j происходит переход к новому элементу той же строки массива и сравнение его значения со значением переменной max.
Если значение элемента массива больше, то max присваивается значение элемента массива с текущим порядковым номером. Когда при данном значении параметра i завершается цикл по параметру j, происходит изменение параметра i и переход к новой строке двумерного массива.
Листинг 2- Программа к примеру 2
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
const int m = 3, n = 4;
int[,] y = new int[m, n] {
{ 2, 2, 8, 9 },
{ 4, 5, 6, 2 },
{ 7, 0, 1, 1 }
};
Console.WriteLine("Исходный массив:");
for (int i = 0; i < m; ++i)
{
for (int j = 0; j < n; ++j)
Console.Write(" " + y[i, j]);
Console.WriteLine();
}
int max=y[0,0];
for (int i = 0; i < m; ++i)
{
for (int j = 0; j < n; ++j)
if (y[i, j] > max) max = y[i, j];
}
Console.WriteLine("Наибольший элемент в матрице "+ max);
Console.Read();
}
}
}
Рисунок 3 - Схема алгоритма к примеру 2
Результаты работы программы:
В листинге 3 продемонстрировано применение элементов класса Аrrау при работе со ступенчатым массивом.
Листинг 3 - Использование методов класса Аrrау для обработки ступенчатого массива
using System;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
int[][] a = new int[3][];
a[0] = new int[5] { 4, 5, 8, 3, 6 };
a[1] = new int[3] { 7, 9, 1 };
a[2] = new int[4] { 6, 5, 3, 1 };
Console.WriteLine("Исходный массив:");
for (int i = 0; i < a.Length; ++i)
{
for (int j = 1; j < a[i].Length; ++j)
Console.Write(" " + a[i][j]);
Console.WriteLine();
}
Console.WriteLine(Array.IndexOf(a[0], 8));
}
}
}
Необходимо обратить внимание на то, как внутри цикла по строкам определяется длина каждого одномерного массива (длина каждой строки массива).
Результаты работы программы:
2.3 Оператор цикла с перебором foreach
Цикл перебора foreach используется для просмотра всех объектов из некоторой группы данных коллекции. В языке С# определен ряд типов коллекций, например, коллекцией являются массивы.
Синтаксис записи цикла foreach:
foreach(тип имя_переменной in имя коллекции) выражение;
где тип и имя_переменной задают тип и имя итерационной переменной, которая в процессе итераций цикла foreach получает значения элементов коллекции, заданной своим именем.
Если в программе в качестве коллекции используется массив данных, то необходимо помнить, что тип итерационной переменной должен совпадать или быть совместимым с базовым типом массива. Необходимо также учитывать, что итерационная переменная как элемент массива доступна только для чтения, и ей нельзя присвоить новое значение, а значит с помощью этой конструкции нельзя изменить и значение элемента массива.
Рассмотрим программу поиска максимального элемента в одномерном массиве.
Листинг 4 - Использование оператора цикла foreach для поиска наибольшего элемента одномерного массива
using System;
namespace ConsoleApplication5
{
class Program
{
static void Main(string[] args)
{
const int n = 6;
int[] a = new int[n] { 3, 12, 5, -9, 8, -4 };
Console.WriteLine("Исходный массив:");
for (int i = 0; i < n; ++i)
Console.WriteLine("\t" + a[i]);
Console.WriteLine();
int max = a[0];
foreach (int x in a)
{
if (x > max)
max = x;
}
Console.WriteLine("Максимальный элемент = " + max);
Console.Read();
}
}
}
Как видно из текста программы цикл foreach последовательно просматривает все элементы массива а и присваивает итерационной переменной х значение очередного элемента массива. Значение х в дальнейшем используется в операторе if для коррекции переменной max.
Результаты работы программы:
Следует отметить тот факт, что не всегда требуется просматривать всю коллекцию до конца, например, в задаче, где требуется найти первый отрицательный элемент. После того как отрицательный элемент найден, можно прервать работу цикла с помощью оператора break.
При работе с многомерными массивами цикл foreach возвращает элементы в порядке следования строк.
Листинг 5 - Использование оператора цикла foreach для поиска наибольшего элемента двумерного массива
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
const int m = 3, n = 4;
int[,] y = new int[m, n] {
{ 2, 2, 8, 9 },
{ 4, 5, 6, 2 },
{ 7, 0, 1, 1 }
};
Console.WriteLine("Исходный массив:");
for (int i = 0; i < m; ++i)
{
for (int j = 0; j < n; ++j)
Console.Write(" " + y[i, j]);
Console.WriteLine();
}
int max = y[0, 0];
foreach (int x in y){
if (x > max) max = x;
}
Console.WriteLine("Наибольший элемент в матрице " + max);
Console.Read();
}
}
}
Как видно из текста программы использование одного оператора foreach позволило заменить два вложенных оператора for в поиске наибольшего элемента двумерного массива.
Результаты работы программы:
3. Варианты заданий для самостоятельной работы
4.1. Титульный лист.
4.2. Краткое теоретическое описание.
4.3. Задание на лабораторную работу, включающее математическую формулировку задачи.
4.4. Результаты выполнения работы, включающие схему алгоритма, тексты программ, результаты вычислений.
PAGE \* MERGEFORMAT 116
EMBED Word.Picture.8
a00
a02
a03
a10
a11
a12
a13
a23
22
a21
a20
a01
0
…
n -1
0
…
m-1
m
n
a[1]
…
…
[0]
a[1]
a
a[0]
[1]
…
…
…
0 1
массив
1
0
Ссылки
на строки