Объявления и инициализация




ГЛАВА 9. МНОГОМЕРНЫЕ МАССИВЫ

В предыдущей главе была рассмотрены аспекты обработки одномерных массивов данных в языке C#, но в повседневной практике приходится разрабатывать алгоритмы значительно сложнее. Очень большой класс задач предполагает работу с массивами более высокой размерности: двумерными, трехмерными и т.д. Язык C# имеет достаточно мощные средства для обработки массивов различной размерности.

Прямоугольные массивы

Прямоугольный массив имеет более одного измерения. Многомернымназывается такой массив, который характеризуется двумя или более измерениями, а доступ к отдельному элементу осуществляется посредством двух или более индексов.

Двумерные массивы являются наиболее простыми из многомерных массивов. К тому же и решение очень многих задач может быть часто сведено к обработке двумерных массивов, поэтому технологии использования двумерных массивов в программах языка С# посвящается целая глава.

Объявления и инициализация

В двумерном массиве позиция любого его элемента определяется двумя индексами. Если представить двумерный массив в виде таблицы данных, то один индекс означает строку, а второй – столбец. Чтобы объявить двумерный массив целочисленных значений размером n * m, достаточно записать следующее:

int[,] имя_массива = new int[n,m];

Следует обратить внимание на то, что синтаксически конструкция вида [,] указывает на создание ссылочной переменной двумерного массива.

Чтобы получить доступ к элементу двумерного массива, используется конструкция переменная с индексами, где необходимо указать оба индекса, разделив их запятой. Например, для присвоения элементу двумерного массива, позиция которого определяется координатами i и j, значение а можно использовать следующую инструкцию:

имя_массива[i,j] = a;

Многомерный массив можно инициализировать, заключив список инициализаторов каждой размерности в собственный набор фигурных скобок. Формат инициализации двумерного массива:

тип[,] имя_массива = {

{val00, val01, val02, …, val0m}

{val10, val11 val12, …, val1m}

{valn0, valn1, valn2, …, valnm}};

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

Ниже приведены различные варианты описания двумерного массива.

Определяются только тип и имя массива, а размер массива и его элементы не заданы. Синтаксис конструкции:

тип[,] имя;

Пример использования для объявления целочисленного массива:

int[,] а;

Определяются не только тип и имя массива, но и с помощью оператора new заданы обе размерности массива и его элементам присвоены значения равные 0. Синтаксис конструкции:

тип[,] имя = new тип [ разм_1, разм_2 ];

Пример использования для объявления целочисленного массива:

int[,] b = new int [2, 3];

Размерность явно не задана, но она вычисляется компилятором по количеству значений в списке инициализации, элементам массива присваиваются значения из списка инициализации:

тип[,] имя = new тип [,] { список_инициализаторов };

Пример использования для объявления целочисленного массива:

int[,] c = new int[,] {{1,2,3},{4,5,6}};

Объявлен массив с типа int, состоящий из двух строк и трех столбцов. Оператор new опущен, но по умолчанию он подразумевается, размерность массива определяется списком инициализаторов, элементам массива присваиваются значения из списка инициализации:

тип[,] имя = { список_инициализаторов };

Пример использования для объявления целочисленного массива:

int[,] с = {{1,2,3},{4,5,6}};

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

тип[,] имя = new тип [ разм1, разм2]{ список_инициализации};

Пример использования для объявления целочисленного массива:

int[,] d = new int[2,3]] {{1,2,3),{4,5,6}}

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

а[1,4] b[i, j] b[j, i]

Необходимо помнить, что компилятор воспринимает первый индекс как номер строки, второй индекс всегда – индекс столбца, независимо от того, как они ни были обозначены в программе.

Примеры

Пример 1. Для целочисленной матрицы размером m*n вычислить сумму элементов в каждой строке (рис. 9.1).

Рисунок 9.1– Матрица из m строк и n столбцов

Нахождение суммы элементов каждой строки требует просмотра матрицы по строкам. Схема алгоритма приведена на рисунке 9.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();

}

}

}

 

Рисунок 9.2– Схема алгоритма к примеру 1

Результат работы программы:

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

Пример 2. Поиск максимального элемента в двумерном массиве.

Схема алгоритма решения данной задачи представлена на рисунке 9.3, а программа в листинге 2.

Решение поставленной задачи осуществляется с помощью цикла по параметру i, изменяющегося шагом +1 от 0 до m-1 с вложенным циклом по параметру j, изменяющемуся шагом +1 от 0 до n-1.

Перед входом в цикл переменной max присваивается значение у[0,0] элемента массива. С каждым изменением параметра j происходит переход к новому элементу той же строки массива и сравнение его значения со значением переменной max.

Если значение элемента массива больше, то max присваивается значение элемента массива с текущим порядковым номером. Когда при данном значении параметра i завершается цикл по параметру j, происходит изменение параметра i и переход к новой строке двумерного массива.

 

 

 


Рисунок 9.3– Схема алгоритма к примеру 2

Листинг 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);

}

}

}

Результаты работы программы:

Ступенчатые массивы

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

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

Объявления и инициализация

При объявлении ступенчатого массива каждая его размерность обозначается парой квадратных скобок:

тип[ ] [ ] имя;

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

int[][] b = new int [3][];

Не смотря на то, что такое объявление указывает количество строк в массиве, память для строк массива еще не выделена. Строки ступенчатого массива в памяти размещаются индивидуально, поэтому под каждый из одномерных массивов, составляющих ступенчатый массив, память требуется выделять явным образом, например:

Выделение памяти под 0-ю строку (5 элементов):

b[0]=new int [5];

Выделение памяти под 1-ю строку (3 элемента):

b[1] =new int [3];

Выделение памяти под 2-ю строку (4 элемента):

b[2] = new int [4];

Здесь b[0 ], b[1] и b[2] – это отдельные массивы, к которым можно обращаться по имени, ниже приведен пример работы со ступенчатым массивом с использованием выделения памяти под каждую строку (лист. 3).

Другой способ выделения памяти:

int[] [] b = {new int[5], new int[3], new int[4]};

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

b[1][2] b[i][j] b[j][i]

В остальном использование ступенчатых массивов не отличается от использования прямоугольных.

Примеры

В листинге 3 продемонстрировано применение элементов класса Аrrау при работе со ступенчатым массивом.

Листинг 3 - Использование методов класса А rrау для обработки ступенчатого массива

using System;

namespace ConsoleApplication3

{ class Program

{ static void Main(string[] args)

{ int[][] b = new int[3][];

b[0] = new int[5] { 4, 5, 8, 3, 6 };

b[1] = new int[3] { 7, 9, 1 };

b[2] = new int[4] { 6, 5, 3, 1 };

 

Console.WriteLine("Исходный массив:");

for (int i = 0; i < b.Length; ++i)

{ for (int j = 1; j < b[i].Length; ++j)

Console.Write(" " + b[i][j]);

Console.WriteLine();

}

Console.WriteLine(Array.IndexOf(b[0], 8));

 

}

}

}

Необходимо обратить внимание на то, как внутри цикла по строкам определяется длина каждого одномерного массива (длина каждой строки массива).

Результат работы программы:



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2019-05-16 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: