Массивы
Мы не будем в тексте лекции разбирать реализацию проекта "Соревнование по триатлону". В видео записи этой лекции разбор был проведен достаточно подробно, а сам проект при желании доступен для просмотра.
Остановимся на правилах, сформулированных в шуточной стихотворной форме, позволяющих лучше запомнить основные моменты в реализации алгоритмов вычисления суммы, произведения, минимального и максимального элементов множества. Правила сформулированы следующим образом:
Правил помнить нужно три:
Объявить,
Задать,
Сравнить, -
Ничего не позабыть!
Правило "Объявить" говорит, что прежде всего следует объявить переменную с содержательным именем, например, min, которая в конечном итоге будет содержать минимальный элемент рассматриваемого множества.
Правило "Задать" говорит, что в момент объявления этой переменной следует задать ей "правильное" значение. Например, при нахождении минимума переменной следует дать значение, заведомо превосходящее значения всех элементов массива.
Правило "Сравнить" говорит, что переменную min следует последовательно сравнивать с элементами множества. Если при сравнении окажется, что некоторый элемент меньше чем min, то переменная min получает новое значение. Это гарантирует, что min является минимальным элементом среди всех просмотренных элементов. Сравнив с этой переменной все элементы множества, мы гарантируем, что min является минимальным элементом всего множества.
Эти три правила действуют при вычислении максимального элемента, при нахождении суммы и произведения элементов множества. В каждом случае следует правильно задавать начальное значение переменной.
Эти правила действуют и тогда, когда рассматривается множество элементов сколь угодно большого размера. Данная лекция как раз посвящена рассмотрению больших множеств. До сих пор мы рассматривали простые данные – числа типа int и double, булевские переменные типа bool, строки текста типа string. Пришла пора познакомиться со сложными структурами данных, без которых невозможно решение практических задач, стоящих перед программистами. Известная книга одного из выдающихся программистов – Никласа Вирта – автора языка Pascal и других языков программирования называется "Программа = Алгоритм + Структура данных". Когда мы создаем программу, то мы должны спроектировать подходящие для решения задачи структуры данных и придумать алгоритм обработки этих данных, приводящий к решению поставленной задачи. Эти две стороны одной программы проектируются одновременно. Нельзя придумать алгоритм, не понимая, как устроены данные. В свою очередь структура данных во многом зависит от алгоритма, обрабатывающего эти данные.
Простейшей из сложных структур данных и, пожалуй, наиболее широко распространенной структурой данных является массив.
Определение
Массивом называется упорядоченная совокупность элементов одного типа.
В этом определении отмечаются две особенности массивов. Во-первых, все элементы массива имеют один и тот же тип. Это требование понятно. Менее понятно, как достигается упорядоченность элементов? Поговорим об этом подробнее. Простым способом упорядочения совокупности элементов является нумерация элементов. В математике широко используется понятие последовательности элементов: a1, a2, a3, … an. Каждый элемент последовательности имеет свой номер, который называют индексом элемента. Индекс однозначно определяет элемент последовательности. Элементы последовательности упорядочены. За элементом с индексом j следует элемент с индексом j+1, а предшествует элемент с индексом j-1. В математике последовательность может иметь бесконечно много элементов. В программировании бесконечности нет и массив всегда имеет конечное число элементов.
Число элементов массива называется его размером. Другая важнейшая характеристика массива его размерность. Размерность массива - это число индексов, используемых для упорядочения элементов массива. Если массив одномерный (размерность равна единице), то массив является аналогом последовательности с конечным числом элементов. Одномерный массив можно рассматривать как строку, содержащую n элементов, где n – размер массива. Двумерный массив можно рассматривать как таблицу, состоящую из m строк и n столбцов. Каждый элемент двумерного массива однозначно характеризуется двумя индексами – номером строки и номером столбца. Размер двумерного массива равен m * n. Увеличивая на единицу размерность массива, мы добавляем новое измерение. Приведу понятную аналогию. Пусть у нас есть тетрадь по арифметике в клеточку. Тогда одна строчка в этой тетради может рассматриваться как одномерный массив, который можно заполнять цифрами. Страничка в тетради представляет собой двумерный массив, а сама тетрадь с пронумерованными страницами является трехмерным массивом. Если в портфеле несколько таких тетрадей и они пронумерованы, то можно говорить о массиве размерности 4. Зная четыре индекса – номер тетради, номер страницы, номер строки и номер столбца, можно однозначно определить, о какой клеточке из всего множества клеточек идет речь и какая цифра записана в этой клеточке.
Объявление массива
Общая схема объявления переменных такова. Объявление может быть сделано без инициализации и тогда оно имеет вид:
<тип переменной><имя переменной>;
При объявлении с инициализацией добавляется значение:
<тип переменной><имя переменной> = <значение переменной>;
Эта схема сохраняется и при объявлении массива. Как указать, что переменная является массивом? В разных языках синтаксис может быть немного различным. В языке C# (C++, Java) это делается так – вначале указывается тип элементов массива, затем в квадратных скобках ставятся запятые в зависимости от размерности массива. Размерность массива равна числу запятых плюс единица. При задании одномерного массива запятые не ставятся.
Пример объявления массивов без инициализации:
int[] ar1, ar2; string[,] sar1;
Здесь ar1 и ar2 – одномерные массивы с элементами типа int. Массив sar1 – это двумерный массив, элементы которого имеют тип string. Заметьте, размер массива не входит в понятие типа массива. Массивы одной размерности и с одним и тем же типом элементов имеют один и тот же тип независимо от размера массива.
При объявлении с инициализацией массивы получают значение. есть две возможности выполнить инициализацию. Первая – задать значение в виде константного массива. Вот пример:
int[] mas = {5, 12, 20, 32};
В этом случае элементы массива задаются списком, заключенным в фигурные скобки. В данном примере массив mas – это одномерный массив размера 4, где первый элемент имеет значение 5, а последний – 32. Сложнее, но возможно задать константный массив размерности больше единицы.
Другая возможность инициализации массива в момент объявления – это создать массив, используя вызов конструктора массива. Вот как это делается:
int[] massiv = new int[10]; double[,] dar = new double[n, m];
В результате этих объявлений создан одномерный целочисленный массив с именем massiv размера 10 и двумерный массив dar с элементами типа double, у которого n строк и m столбцов. Переменные n и m должны быть целочисленного типа и иметь значения в момент объявления массива dar. Ключевое слово new в этих объявлениях задает вызов конструктора, создающего массив. Остается выяснить, какие же значения имеют элементы массива, созданного конструктором? Ведь в отличие от задания константного массива, никакие значения конструктору массива не передаются. Ответ прост. Все элементы массива получают одно и тоже значение, определяемое значением по умолчанию, принятого для элементов заданного типа. Для арифметических типов int и double значением по умолчанию является число ноль, для типа string – пустая строка.