Введение в массивы

Массивы в языке C

В языке C массив - это набор однотипных элементов, расположенных в памяти друг за другом. Для объявления массива и доступа к элементам используется простейший синтаксис:

1
2
3
4
5
6
7
int main() {
    int a[5]; // массив из 5 элементов типа int
    double b[5][10]; // массив из 5 массивов по 10 элементов типа double

    a[0] = -1;
    b[0][0] = 1.0;
}

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

1
2
3
4
5
6
7
int main() {
    const int N = 5;
    int a[N] = {1, 2, 3, 4, 5};
    for (int i = 0; i < N; ++i) {
        cout << a[i] << " ";
    }
}

Массивы в языке C - это статичесие структуры данных, то есть их размер должен быть известен на момент компиляции. Поэтому размер массива должен быть константой или выражением, вычисляемым на этапе компиляции. Безусловно, это очень сильно ограничивает использование стандартных массивов в реальном мире. И хотя в C есть возможность написания динамических массивов с помощью работы с динамической памятью, это малоприменимо в олимпиадном программировании.

Массивы в языке C++

В C++ поддержана концепция ООП - то есть появилась возможность создавать свои типы данных, у которых есть свои методы и свойства. В частости, благодаря этому появилась возможность создавать удобные в использовании динамические массивы.

В языке C++ есть и прямой аналог массивов из языка C - array. Однако говоря о массиве, мы будем всегда подразумевать динамические массивы. Для создания динамического массива в C++ используется класс vector из стандартной библиотеки:

1
2
3
4
5
6
7
int main() {
    vector<int> a = {1, 2, 3, 4, 5};
    a.push_back(6); // добавление элемента в конец массива
    for (int i = 0; i < a.size(); ++i) {
        cout << a[i] << " ";
    }
}

Обратите внимание, мы уже воспользовались двумя методами вектора:

  1. push_back() - добавляет элемент в конец вектора. Это и есть основное преимущество вектора перед массивом - вектор эффективно поддерживает операцию добавляения в конец.
  2. size() - возвращает размер вектора. В языке C имея переменную-массив, мы не можем узнать его размер, так как размер массива не хранится в памяти. В C++ же размер вектора хранится в памяти, поэтому мы можем узнать его в любой момент.

О других методах вектора и других контейнерах вы узнаете в следующих лекциях.

В треугольных скобах пишется тип элементов массива. В данном случае это int. Если же нам надо создать двумерный массив размера n x m, то можно воспользоваться вложенными векторами:

1
2
3
4
5
int main() {
    int n = 5, m = 10;
    vector<vector<double>> a(n, vector<double>(m));
    a[0][0] = 1.0;
}

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

  1. vector<double> a(m) - создает вектор из m элементов типа double.
  2. vector<double> a(m, 1.0) - создает вектор из m элементов типа double и заполняет его единицами.
  3. vector<vector<double>> a(n, vector<double>(m)) - создает вектор из n элементов типа vector<double>, каждый из которых содержит m элементов типа double, то есть создает двумерный массив размера n x m.

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